欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

python包裝和授權(quán)學(xué)習(xí)教程

 更新時(shí)間:2023年06月14日 14:29:35   作者:Mindtechnist  
包裝是指對一個(gè)已經(jīng)存在的對象進(jìn)行系定義加工,實(shí)現(xiàn)授權(quán)是包裝的一個(gè)特性,下面這篇文章主要給大家介紹了關(guān)于python包裝和授權(quán)的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下

前言

所有便準(zhǔn)數(shù)據(jù)類型都可以通過兩種方式產(chǎn)生,一種是直接定義,一種是使用相應(yīng)的函數(shù),比如要產(chǎn)生字符串,可以s=’hello’或s=str(hello)。像str這種函數(shù)都是工廠函數(shù),實(shí)際上工廠函數(shù)都是類,我們可以通過繼承這些類來定制自己的數(shù)據(jù)類型。(包裝)

包裝

python為大家提供了標(biāo)準(zhǔn)數(shù)據(jù)類型,以及豐富的內(nèi)置方法,其實(shí)在很多場景下我們都需要基于標(biāo)準(zhǔn)數(shù)據(jù)類型來定制我們自己的數(shù)據(jù)類型,新增/改寫方法,這就用到了繼承/派生知識(其他的標(biāo)準(zhǔn)類型均可以通過下面的方式進(jìn)行二次加工)。

二次加工標(biāo)準(zhǔn)類型(基于繼承實(shí)現(xiàn))

class List(list): #繼承l(wèi)ist所有的屬性,也可以派生出自己新的,比如append和mid
    def append(self, p_object):
        ' 派生自己的append:加上類型檢查'
        if not isinstance(p_object,int): #if type(p_object) is int:
            raise TypeError('must be int')
        #self.append(p_object) #死循環(huán)
        #list.append(self, p_object) #調(diào)用父類的方法
super().append(p_object) #調(diào)用父類的方法

    @property
    def mid(self):
        '新增自己的屬性'
        index=len(self)//2
        return self[index]

l=List([1,2,3,4])
print(l)
l.append(5)
print(l)
# l.append('1111111') #報(bào)錯(cuò),必須為int類型

print(l.mid)

#其余的方法都繼承l(wèi)ist的
l.insert(0,-123)
print(l)
l.clear()
print(l)

clear加權(quán)限限制

class List(list):
    def __init__(self,item,tag=False):
        super().__init__(item)
        self.tag=tag
    def append(self, p_object):
        if not isinstance(p_object,str):
            raise TypeError
        super().append(p_object)
    def clear(self):
        if not self.tag:
            raise PermissionError
        super().clear()

l=List([1,2,3],False)
print(l)
print(l.tag)

l.append('saf')
print(l)

# l.clear() #異常

l.tag=True
l.clear()

授權(quán)

授權(quán)是包裝的一個(gè)特性, 包裝一個(gè)類型通常是對已存在的類型的一些定制,這種做法可以新建,修改或刪除原有產(chǎn)品的功能。其它的則保持原樣。授權(quán)的過程,即是所有更新的功能都是由新類的某部分來處理,但已存在的功能就授權(quán)給對象的默認(rèn)屬性。

授權(quán)是采用已存在的功能達(dá)到最大限度的代碼重用。在包裝中我們可以新建、修改或刪除已有的功能,授權(quán)的過程就是將更新的功能交由新類來處理,已存在的功能就授權(quán)給對象的默認(rèn)屬性。

實(shí)現(xiàn)授權(quán)的關(guān)鍵點(diǎn)就是覆蓋__getattr__方法 (包裝是通過繼承實(shí)現(xiàn))。在代碼里包含一個(gè)對getattr()內(nèi)建函數(shù)的調(diào)用,調(diào)用getattr()得到默認(rèn)對象的屬性(數(shù)據(jù)屬性或者方法)并返回它,以便于訪問或者調(diào)用。

當(dāng)引用一個(gè)屬性時(shí),解釋器首先會在局部名稱空間中查找那個(gè)名字,比如一個(gè)自定義的方法或局部實(shí)例屬性。如果沒有在局部字典中找到,則搜索類名稱空間,以防一個(gè)類屬性被訪問。最后,如果兩類搜索都失敗了,搜索則對原對象開始授權(quán)請求,此時(shí)__getattr__()會被調(diào)用。

示例1

import time
class FileHandle:
    def __init__(self,filename,mode='r',encoding='utf-8'):
        self.file=open(filename,mode,encoding=encoding)
    def write(self,line): #定制自己的write方法 – 對寫入的內(nèi)容加上時(shí)間
        t=time.strftime('%Y-%m-%d %T')
        self.file.write('%s %s' %(t,line))

    def __getattr__(self, item):
        return getattr(self.file,item)# self.file是通過系統(tǒng)默認(rèn)的open獲取的,它包含了默認(rèn)open的所有方法,item是一個(gè)字符串,getattr以字符串形式調(diào)用方法

f1=FileHandle('b.txt','w+')
f1.write('你好啊')
f1.seek(0)
print(f1.read()) 
f1.close()

在實(shí)例和類FileHandle中都沒有找到該屬性,所以觸發(fā)__getattr__先找f1的屬性字典,沒有則找類FileHandle的屬性字典,沒有則觸發(fā)__getattr__,__getattr__中調(diào)用的是系統(tǒng)open返回的文件描述符的方法,通過自己的類實(shí)例化,調(diào)用系統(tǒng)的方法。

示例2

#_*_coding:utf-8_*_
__author__ = 'Linhaifeng'
#我們來加上b模式支持
import time
class FileHandle:
    def __init__(self,filename,mode='r',encoding='utf-8'):
        if 'b' in mode:
            self.file=open(filename,mode)
        else:
            self.file=open(filename,mode,encoding=encoding)
        self.filename=filename
        self.mode=mode
        self.encoding=encoding

    def write(self,line):
        if 'b' in self.mode:
            if not isinstance(line,bytes):
                raise TypeError('must be bytes')
        self.file.write(line)

    def __getattr__(self, item):
        return getattr(self.file,item)

    def __str__(self):
        if 'b' in self.mode:
            res="<_io.BufferedReader name='%s'>" %self.filename
        else:
            res="<_io.TextIOWrapper name='%s' mode='%s' encoding='%s'>" %(self.filename,self.mode,self.encoding)
        return res
f1=FileHandle('b.txt','wb')
# f1.write('你好啊啊啊啊啊') #自定制的write,不用在進(jìn)行encode轉(zhuǎn)成二進(jìn)制去寫了
f1.write('你好啊'.encode('utf-8'))
print(f1)
f1.close()

示例3

class List:
    def __init__(self,seq):
        self.seq=seq

    def append(self, p_object):
        ' 派生自己的append加上類型檢查,覆蓋原有的append'
        if not isinstance(p_object,int):
            raise TypeError('must be int')
        self.seq.append(p_object)

    @property
    def mid(self):
        '新增自己的方法'
        index=len(self.seq)//2
        return self.seq[index]

    def __getattr__(self, item):
        return getattr(self.seq,item)

    def __str__(self):
        return str(self.seq)

l=List([1,2,3])
print(l)
l.append(4)
print(l)
# l.append('3333333') #報(bào)錯(cuò),必須為int類型

print(l.mid)

#基于授權(quán),獲得insert方法
l.insert(0,-123)
print(l)

示例4

class List:
    def __init__(self,seq,permission=False):
        self.seq=seq
        self.permission=permission
    def clear(self):
        if not self.permission:
            raise PermissionError('not allow the operation')
        self.seq.clear()

    def __getattr__(self, item):
        return getattr(self.seq,item)

    def __str__(self):
        return str(self.seq)
l=List([1,2,3])
# l.clear() #此時(shí)沒有權(quán)限,拋出異常

l.permission=True
print(l)
l.clear()
print(l)

#基于授權(quán),獲得insert方法
l.insert(0,-123)
print(l)

__setattr__,__delattr__,__getattr__

class Foo:
    x=1
    def __init__(self,y):
        self.y=y

    def __getattr__(self, item):
        print('----> from getattr:你找的屬性不存在')

    def __setattr__(self, key, value):
        print('----> from setattr')
        # self.key=value #這就無限遞歸了,因?yàn)樵O(shè)置屬性會觸發(fā)__setattr__
        # self.__dict__[key]=value #應(yīng)該使用它,直接修改底層字典

    def __delattr__(self, item):
        print('----> from delattr')
        # del self.item #無限遞歸了
        self.__dict__.pop(item)# 直接在底層字典刪除,就不會觸發(fā)了

#__setattr__添加/修改屬性會觸發(fā)它的執(zhí)行
f1=Foo(10)
print(f1.__dict__) # 因?yàn)槟阒貙懥薩_setattr__,凡是賦值操作都會觸發(fā)它的運(yùn)行,你啥都沒寫,就是根本沒賦值,除非你直接操作屬性字典,否則永遠(yuǎn)無法賦值
f1.z=3
print(f1.__dict__)

#__delattr__刪除屬性的時(shí)候會觸發(fā)
f1.__dict__['a']=3#我們可以直接修改屬性字典,來完成添加/修改屬性的操作
del f1.a
print(f1.__dict__)

#__getattr__只有在使用點(diǎn)調(diào)用屬性且屬性不存在的時(shí)候才會觸發(fā)
f1.xxxxxx

getattr(obj)相當(dāng)于obj.__getattr__()
setattr(obj)相當(dāng)于obj.__setattr__()
delattr(obj)相當(dāng)于obj.__delattr__()

  • 類的內(nèi)置attr屬性,你不定義的話會用默認(rèn)的,如果定義了則用自己定義的。
  • class.at 調(diào)用時(shí)觸發(fā):如果類class中屬性at不存在,則觸發(fā)__getattr__
  • del class.at刪除時(shí)觸發(fā):刪除類class的屬性at時(shí),觸發(fā)__delattr__
  • class.at=1設(shè)置時(shí)觸發(fā):設(shè)置類class的屬性at時(shí),觸發(fā)__setattr__

自己定義這三個(gè)函數(shù),在相應(yīng)操作時(shí),就可以觸發(fā)自己想要的邏輯。

class MyClass:
def __init__(self, name)
    self.name = name #觸發(fā)__setattr__
def __getattr__(self, item) #默認(rèn)的__getattr__是屬性不存在則報(bào)錯(cuò),我們修改后不報(bào)錯(cuò),僅打印提示
    print(“attr [%s] not found” %item)
def __setattr__(self, k, v) #默認(rèn)的setattr會把設(shè)置的屬性加在屬性字典,但是我們自定義的setattr什么也沒做,屬性字典不會增加屬性
    print(‘set attr', k, v)
    if tyoe(v) is str: #限制value只能以字符串的形式設(shè)置
        print(‘set')
        #self.k = v #再次觸發(fā)__setattr__,進(jìn)入死循環(huán)
        self.__dict__[k] = v.upper() 
#真正的設(shè)置 – 直接操作底層數(shù)據(jù)結(jié)構(gòu),在屬性字典中添加
    else:
        print(‘not str')
def __delattr__(self, item)
    """ #自己控制-所有屬性不可刪除
    print(‘can not delete [%s]' %item)
    pass
    """
    print(‘delete attr[%s]' %item)
    #del self.item #觸發(fā)__delattr__ 進(jìn)入死循環(huán)
    self.__dict__.pop(item) #真正的刪除

mc = MyClass(‘hello') #實(shí)例化的時(shí)候會觸發(fā)__init__
print(mc.name) #hello
print(mc.hhh) #觸發(fā)__getattr__  mc?self  hhh?item(字符串的形式)
mc.age = 18
mc.age = ‘18' #觸發(fā)__setattr__  mc?self  age?k  ‘18'?v
del mc.name #觸發(fā)__delattr__  mc?self  name? item(字符串的形式)

__getattribute__

#__getattr__
class Foo:
    def __init__(self,x):
        self.x=x
    def __getattr__(self, item):
        print('執(zhí)行的是我')
        # return self.__dict__[item]
f1=Foo(10)
print(f1.x)
f1.xxxxxx #不存在的屬性訪問,觸發(fā)__getattr__
#__getattribute__ - 不管屬性是否存在,都會觸發(fā)
class Foo:
    def __init__(self,x):
        self.x=x

    def __getattribute__(self, item):
        print('不管是否存在,我都會執(zhí)行')

f1=Foo(10)
f1.x
f1.xxxxxx

如果二者同時(shí)出現(xiàn)

#_*_coding:utf-8_*_
__author__ = 'Linhaifeng'

class Foo:
    def __init__(self,x):
        self.x=x

    def __getattr__(self, item):
        print('執(zhí)行的是我')
        # return self.__dict__[item]
    def __getattribute__(self, item):
        print('不管是否存在,我都會執(zhí)行')
        raise AttributeError('哈哈') #拋出AttributeError異常–跳轉(zhuǎn)到__getattr__

f1=Foo(10)
f1.x
f1.xxxxxx

當(dāng)__getattribute__與__getattr__同時(shí)存在,只會執(zhí)行__getattribute__,除非__getattribute__在執(zhí)行過程中拋出異常AttributeError,系統(tǒng)默認(rèn)的__getattribute__,如果查找的屬性不存在,當(dāng)拋出異常AttributeError的時(shí)候,會跳轉(zhuǎn)到__getattr__,也就是說,只有拋出異常AttributeError的時(shí)候,才會執(zhí)行__getattr__,其他情況下只會執(zhí)行__getattribute__。系統(tǒng)提供的默認(rèn)__getattribute__,當(dāng)要查找的屬性存在時(shí),會在當(dāng)前屬性字典中返回屬性,如果要找的屬性不存在會拋出異常AttributeError,轉(zhuǎn)到__getattr__去執(zhí)行,__getattr__接收異常來避免程序崩潰,并執(zhí)行定義好的邏輯。

總結(jié)

到此這篇關(guān)于python包裝和授權(quán)的文章就介紹到這了,更多相關(guān)python包裝和授權(quán)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • asyncio異步編程之Task對象詳解

    asyncio異步編程之Task對象詳解

    這篇文章主要為大家詳細(xì)介紹了asyncio異步編程之Task對象,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-03-03
  • 詳解python的內(nèi)存分配機(jī)制

    詳解python的內(nèi)存分配機(jī)制

    Python的內(nèi)存分配機(jī)制是小白們最需要理解的概念之一。創(chuàng)建對象(變量、函數(shù)、對象等)后,CPython會在內(nèi)存中為其分配地址。Python有一個(gè)id()函數(shù),它可以返回對象的“身份”,也就是內(nèi)存地址。它實(shí)際上是一個(gè)唯一的整數(shù)。
    2021-05-05
  • 用Python配平化學(xué)方程式的方法

    用Python配平化學(xué)方程式的方法

    在本篇文章中小編給大家整理的是關(guān)于用Python配平化學(xué)方程式的方法以及相關(guān)注意知識點(diǎn),需要的朋友們參考學(xué)習(xí)下。
    2019-07-07
  • Python爬蟲之教你利用Scrapy爬取圖片

    Python爬蟲之教你利用Scrapy爬取圖片

    這篇文章主要介紹了Python爬蟲之教你利用Scrapy爬取圖片,文中有非常詳細(xì)的代碼示例,對正在學(xué)習(xí)python的小伙伴們有非常好的幫助,需要的朋友可以參考下
    2021-04-04
  • 快速解決PyCharm無法引用matplotlib的問題

    快速解決PyCharm無法引用matplotlib的問題

    今天小編就為大家分享一篇快速解決PyCharm無法引用matplotlib的問題,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-05-05
  • 使用pandas讀取文件的實(shí)現(xiàn)

    使用pandas讀取文件的實(shí)現(xiàn)

    這篇文章主要介紹了使用pandas讀取文件的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-07-07
  • 一步步教你用python給女朋友寫個(gè)微信自動(dòng)提醒的程序

    一步步教你用python給女朋友寫個(gè)微信自動(dòng)提醒的程序

    如今微信已成為我們?nèi)粘I畹闹饕涣鞴ぞ?但是微信自身的功能有時(shí)候可能并不能滿足我們的需要,因此我們會想是否可以進(jìn)行微信功能的拓展呢,這篇文章主要給大家介紹了關(guān)于利用python給女朋友寫了個(gè)微信自動(dòng)提醒程序的相關(guān)資料,需要的朋友可以參考下
    2021-10-10
  • CentOS下Python3的安裝及創(chuàng)建虛擬環(huán)境的方法

    CentOS下Python3的安裝及創(chuàng)建虛擬環(huán)境的方法

    這篇文章主要介紹了CentOS下Python3的安裝及創(chuàng)建虛擬環(huán)境的方法,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2018-11-11
  • python基礎(chǔ)教程之循環(huán)介紹

    python基礎(chǔ)教程之循環(huán)介紹

    這篇文章主要介紹了python基礎(chǔ)教程之循環(huán)介紹,本文講解了for循環(huán)、while循環(huán)、中斷循環(huán)等python的基礎(chǔ)知識,需要的朋友可以參考下
    2014-08-08
  • 最新版 Windows10上安裝Python 3.8.5的步驟詳解

    最新版 Windows10上安裝Python 3.8.5的步驟詳解

    這篇文章主要介紹了最新版 Windows10上安裝Python 3.8.5的步驟詳解,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-11-11

最新評論