1. 程式人生 > >Python之各種內置方法

Python之各種內置方法

存在 === 目的 ots ror get slot 一個 hide

1、attr 系列

技術分享圖片
class foo:
    def __init__(self,NAME):
        self.name=NAME

    def __setattr__(self, key, value):
        # 作用:可以對 value 進行類型限制
        if not isinstance(value,str): # 對 value 限制只能是字符串
            raise TypeError(must be str)
        # print(‘setattr----key:%s,value:%s‘%(key,value))
# print(type(key)) # key 是字符串類型 # print(type(value)) # self.key=value # key 是字符串類型,self.屬性,屬性不能為字符串類型,不能這樣賦值 # setattr(self,key,value) # 跟上面一樣 self.key=valuse 會觸發 setattr 的執行,會造成遞歸 self.__dict__[key]=value # 直接在對象的 dict 字典裏面操作 def __delattr__(self, item):
print(delattr:%s%item) # del self.__dict__[item] # 同樣,刪除直接去刪除對象的字典,法1 self.__dict__.pop(item) # 法2 def __getattr__(self, item): print(getattr:%s%item) f1=foo(egon) # f1.name=‘egon‘ 賦值操作會先觸發setattr 的執行 f1.age=18 del f1.age print(f1.__dict__) getattr 單獨拿出來
class foo: def __init__(self, NAME): self.name = NAME # 只有屬性不存在才會觸發 getattr 的執行 def __getattr__(self, item): print(getattr:%s %s % (item,type(item))) f1 = foo(egon) # f1.name=‘egon‘ 賦值操作會先觸發setattr 的執行 # print(f1.name) print(f1.xxxx) # 屬性不存在才會觸發 getattr 的執行
View Code

2、item 系列

技術分享圖片
__setitem__(self,key,value):當對類中的某個屬性進行"賦值"時觸發的函數(只有使用字典賦值的方式時才會觸發此方法的執行)
與Attr系列的區分:__setattr__(self):是在對象打點兒的方式賦值時,才會觸發的方法

class Foo:
    def __setitem__(self, key, value):
        print(key,"獲得",value)
f = Foo()
f["name"] = "egon"   value = egon
__setitem__ 技術分享圖片
__delitem__(self,key):當類中的某個屬性被刪除時,觸發此方法(只有使用del字典方式刪除屬性時,才會觸發此方法)
與Attr系列的區分:__delattr__(self):使用del類打點兒屬性的方式刪除屬性,才會觸發此方法

class Foo:
    name = "egon"
    def __delitem__(self, key):
        print(key,"已被刪除")
f = Foo()
del f["name"]
__delitem__ 技術分享圖片
__getitem__(self,item):當調用類中的屬性或方法時觸發此方法的執行(只在使用類[key]字典的方式調用時,才會觸發此方法)
與Attr系列的區分:其實這裏已經很明顯了,__getattr__(self):是類打點兒調用且命名空間沒有發現名字的情況下,觸發此方法
class Foo:
    name = "egon"
    def __getitem__(self, item):
        print(item,"已被調用")
f = Foo()
f["name"]
__getitem__

3、__slost__

__slost__:其實就是將類中的名稱鎖定,實例化對象,只可以賦值和調用,不可以刪除屬性和增加新的屬性

應用場景:當實例化幾萬個對象的時候,每個對象都會生成一個名稱空間__dict__,而每一個名稱空間都會各自占用一個內存,造成內存的浪費,用 __slost__,不用再產生 dict 了,省內存,對象的 dict 都統一用類的 dict,屬性都是用 slost 給定義的

技術分享圖片
class Foo:
    __slots__ = ["x","y"]#在類中定義屬性x和y
f = Foo()#實例化Foo
f.x = 1#此時我們可以使用實例化對象調用類中的屬性x
f.y = 2
#如果現在,我們在實例化對象中增加一個z
f.z = 3
#會得到如下錯誤
#AttributeError: ‘Foo‘ object has no attribute ‘z‘
#也就是不可以,對實例化對象增加新的屬性
#如果現在,我們在實例化對象中刪除一個x
del f.x#此時程序執行並不會出錯,但是我們打印一下Foo的命名空間
print(Foo.__dict__)
#{‘__doc__‘: None, ‘y‘: <member ‘y‘ of ‘Foo‘ objects>, ‘__module__‘: ‘__main__‘, ‘x‘: <member ‘x‘ of ‘Foo‘ objects>, ‘__slots__‘: [‘x‘, ‘y‘]}
#依然可以看到x的存在,所以,實例化對象不可以刪除__slots__定義的屬性
例1 技術分享圖片
class Foo:
    __slots__ = ["x","y"]
Foo.__slots__ = "z"
print(Foo.__dict__)
#{‘__doc__‘: None, ‘x‘: <member ‘x‘ of ‘Foo‘ objects>, ‘__slots__‘: ‘z‘, ‘__module__‘: ‘__main__‘, ‘y‘: <member ‘y‘ of ‘Foo‘ objects>}
del Foo.x
print(Foo.__dict__)
#{‘__doc__‘: None, ‘__slots__‘: ‘z‘, ‘__module__‘: ‘__main__‘, ‘y‘: <member ‘y‘ of ‘Foo‘ objects>}
# f.z=3  對象也無法賦值
__slots__只是針對實例化對象的禁錮,直接對類中的屬性進行修改,是可以的
例2

4、__next__ 和 __iter__

技術分享圖片
class foo:
    def __init__(self,start):
        self.start=start

    def __next__(self):
        return self

    def __iter__(self):
        n=self.start
        self.start=+1
        return self


f=foo(0)
print(next(f))  # f.__next__()
print(next(f))  # f.__next__()

for i in f:  # 執行 i=f.__iter__ 方法,轉化為一個叠代器
    print(i)   #  next(i) 執行 next 方法
View Code

5、__del__

這個是在回收實例化對象時觸發執行的方法

每當 del 實例化對象時會觸發

或者是程序結束時,會觸發,總之就是實例化對象失效時都會執行__del__方法

註:此方法一般無須定義,因為Python是一門高級語言,程序員在使用時無需關心內存的分配和釋放,因為此工作都是交給Python解釋器來執行,所以,析構函數的調用是由解釋器在進行垃圾回收時自動觸發執行的

技術分享圖片
class Foo:
    def __del__(self):
        print(self,"被釋放掉了")

f = Foo()
print(f)
del f



import time
class Open:
    def __init__(self,file,mode=r,encoding=utf8):
        self.x=open(file,mode=mode,encoding=encoding)
        self.file=file
        self.mode=mode
        self.encoding=encoding

    def write(self):
        pass

    def __del__(self):
        print(del)
        self.x.close()


# Open(‘a.txt‘,‘w‘) 需要開辟一個內存空間來存放值,產生一個對象,變量 f 與它進行綁定,此時 f 在引用,引用計數不為0
# 當引用計數為 0 的時候,就去對象裏面找 析構函數 del
f=Open(a.txt,w)  #  當跑完程序,f 與Open 的綁定關系就解除,觸發 del 的執行,回收值的內存
del f  # 下面程序還沒跑完,就執行 del,刪除 f ,Open 沒有被引用,引用計數為 0 ,回收 Open
time.sleep(1000)


# 註意,如果沒有 del 方法,對象被刪除後,不會被立即回收,python回收機制會定期去回收
View Code

6、__str__

技術分享圖片
class Pepole:
    def __init__(self,name,age):
        self.name=name
        self.age=age

    def __str__(self):  # 
        return abc  # __str__ 方法必須返回字符串

obj=Pepole(egon,18)
print(obj)  # 當打印對象的時候觸發 __str__方法
View Code

7、__enter__和__exit__

所謂上下文管理協議,就是咱們打開文件時常用的一種方法:with

__enter__(self):當with開始運行的時候觸發此方法的運行

__exit__(self, exc_type, exc_val, exc_tb):當with運行結束之後觸發此方法的運行

exc_type如果拋出異常,這裏獲取異常的類型

exc_val如果拋出異常,這裏顯示異常內容

exc_tb如果拋出異常,這裏顯示所在位置

用途或者說好處:

1.使用with語句的目的就是把代碼塊放入with中執行,with結束後,自動完成清理工作,無須手動幹預

2.在需要管理一些資源比如文件,網絡連接和鎖的編程環境中,可以在__exit__中定制自動釋放資源的機制,你無須再去關系這個問題,這將大有用處

技術分享圖片
class Foo:
    def __enter__(self):
        print(=======================》enter)
        return 111111111111111

    def __exit__(self, exc_type, exc_val, exc_tb):
        print(exit)
        print(exc_type,exc_type)
        print(exc_val,exc_val)
        print(exc_tb,exc_tb)
        return True  # 如果不加這一行,表示抓到報錯,整個程序退出,不再往下執行
    # 如果__exit()返回值為True,那麽異常會被清空,就好像啥都沒發生一樣,with後的語句正常執行


# with Foo(): #res=Foo().__enter__()
#     pass

with Foo() as obj: #res=Foo().__enter__() #obj=res
    print(with foo的自代碼塊,obj)
    raise NameError(名字沒有定義) # with語句中代碼塊出現異常,則with後的代碼都無法執行
        print(************************************)

# 執行與否,看 exit 返回的是否 true
print(1111111111111111111111111111111111111111)
例1 技術分享圖片
class Open:
    def __init__(self,file,mode=r,encoding=utf8):
        # 使用系統函數open()傳入相應打開文件所需的參數,將文件句柄傳遞給self.f
        self.f=open(file,mode=mode,encoding=encoding)

    def __enter__(self):
        return self 
    # 這裏要返回 self 而不是 self.f,self.f 是調用真實的 open 文件操作的方法
        # 這裏 self 調用的是 Open 類裏面的各個函數屬性

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.f.close()
        print(關閉)

    def write(self,line): #自己定義write方法
        print(ok)
        self.f.write(line) #使用self.f 文件句柄 write 方法將內容寫入文件

    # 利用__getattr__(),Attr系列中的getattr,當對象沒有找到Open中傳遞過來的名字時,調用此方法
    def __getattr__(self, item):
        return getattr(self,item) # 返回self.f 文件句柄中,被對象調用,且不在Open類中的名字

with Open(a.txt,w,encoding=utf8) as obj:
    # obj=Open(‘a.txt‘,‘w‘,encoding=‘utf8‘)
    obj.write(123)
    # 調用的是類裏面的 write 方法,方法裏面有 obj.f.write 調用真實的 write
例2

8、__doc__

描述信息用的

技術分享圖片
class Foo:
    我是描述信息
    pass

print(Foo.__doc__)


class Foo:
    我是描述信息
    pass

class Bar(Foo):
    pass
print(Bar.__doc__) #該屬性無法繼承給子類

該屬性無法被繼承
View Code

9、__call__

對象後面加括號,觸發執行。

註:構造方法的執行是由創建對象觸發的,即:對象 = 類名() ;而對於 __call__ 方法的執行是由對象後加括號觸發的,即:對象() 或者 類()()

技術分享圖片
class Foo:

    def __init__(self):
        pass
    
    def __call__(self, *args, **kwargs):

        print(__call__)


obj = Foo() # 執行 __init__
obj()       # 執行 __call__
View Code

.

Python之各種內置方法