python基礎八
- 2019 年 10 月 6 日
- 筆記
類的內置方法
補充:
其實比如str()這個內置函數,都是在內部調用__str__方法。
之所以提供str()這種方法大概是更簡潔吧,有興趣的可以去看一下源碼。
str(123456)實際上是123456.__str__()
實例:
a = 123456
b = str(123456)
c = a.__str__
print(b) # 輸出123456,看不出是字元串類型,你可以type()下
print(c) # 輸出一個記憶體地址,也就是存放這個字元串的記憶體地址
print(c()) # 輸出123456,用一個記憶體地址加上一個括弧就是執行
print(repr(b)) # 利用repr方法輸出 '123456',可以看出是字元串類型,同時你也可以type()
print(repr(c())) # 同上,輸出 '123456'
__str__
class A:
def __str__(self):
return '我是__str__方法'
a = A()
print(a)
輸出:我是__str__方法
你會覺得不可思議吧,但是確確實實是這樣,當我們輸出a的時候,實際上是輸出a.__str__()方法,友誼之前我們沒有寫這個方法,所以就會調用object中的__str__方法,因為所有沒有繼承的類,默認是繼承object類的,在子類中沒有找到__str__方法就會去父類object中找。
列表實例化輸出:
list = [1,2,3,4,5]
print(list)
#那麼這裡為什麼會直接輸出一個列表,而不是一個記憶體地址,實際上就是重構了__str__方法。
註:返回值必須為字元串類型
__repr__
class Person:
def __init__(self,name):
self.name = name
def __repr__(self):
return self.name
p = Person('張三')
print(repr(p)) # 輸出 張三
print('我的名字是%r'%p) # 輸出 我的名字是張三 %r就是調用的__repr__()方法,同理%s?你應該懂吧。如果我們不寫repr方法,它就會調用父類的方法,會輸出一個記憶體地址。
註:當我們在類中寫了repr方法,沒有寫str方法,我們再次輸出str(Person)他不會輸出記憶體地址,會輸出repr中的內容,我們理解為他找不到str方法就會找repr方法,repr方法再沒有就會輸出記憶體地址,但是反過來不行。(莫名的備胎)這個repr方法也必須返回字元串。
__del__
class A:
def __init__(self,name):
self.name = name
def __del__(self):
print('執行__del__方法')
a = A('張三')
del a.name
print(a.name)
輸出:
'A' object has no attribute 'name'
執行__del__方法
報錯了,說明刪除了name這個屬性,並且執行力__del__中的方法。和上面兩個不一樣。
註:放我們調用完這個一會執行__del__方法,但是沒有刪除變數。python這個方法內部有個引用計數機制,
當計數為0的時候,就會刪除這個屬性。來釋放記憶體。
實例:
class A:
def __init__(self,name):
self.name = name
def __del__(self):
print('執行__del__方法')
a = A('張三')
import time
time.sleep(1)
print(a.name)
輸出:
張三
執行__del__方法
可以看到,我們並沒有調用__del__方法,但是再調用完之後會自動調用這個方法。並且看一下執行順序,也就是說,先輸出,再調用__del__方法。也就是說先執行__del__中的方法,再進行刪除,也就是說我們可以在__del__寫一些收尾工作,比如f.close()。
__call__
class A:
def __call__(self):
print('執行了__call__方法')
a = A()
a()
輸出:執行了__call__方法
也就是a()就是執行了__call__方法。
__getitem__
class A:
def __init__(self,name,age):
self.name = name
self.age = age
def __getitem__(self,item):
return self.__dict__[item]
a = A('張三',18)
print(a['name'])
輸出:張三
我們實例化之類後,a['name'],就是調用內置方法__getitem__中的內容。
__setitem__
class A:
def __init__(self,name,age):
self.name = name
self.age = age
def __setitem__(self,key,value):
self.__dict__[key] = value
a = A('張三',18)
a['sex'] = '男'
print(a.sex)
輸出:男
也同樣,當我們a['sex'] = '男'的時候,調用的是 __setitem__方法。
__delitem__
class A:
def __init__(self,name,age):
self.name = name
self.age = age
def __delitem__(self,key):
del self.__dict__[key]
a = A('張三',18)
del a['name']
這樣就刪除了,其實我會覺得像刪除不是有方法嗎,這種方法是以將對象以字典的形式查,那麼對於字典和列表你可能又有了新的認識。在object中對應的是__delattr__方法。
__new__
我們知道__init__是在實例化的時候就會執行,在他之前會執行__new__方法。
class A:
def __init__(self,name,age):
self.name = name
self.age = age
def __new__(cls,*args,**kwargs):
return object.__new__(A,*args,**kwargs)
__new__可以決定調用哪個類的_init_方法,如果有兩個類,並且是繼承關係,就可以選擇調用父類的__init__方法,__init__的self就是__new__實例化的結果。有興趣的可以去了解一下。
__eq__
class A:
def __init__(self,name):
self.name =name
def __eq__(self,other):
return self == other
a = A('張三')
b = A('張三')
print(a==b)
返回False,==是調用了__eq__方法,修改成:
def __eq__(self,other):
return True
就會返回True,但是也不能這樣寫是吧,我們判斷名字相等就讓他返回True
def __eq__(self,other):
if self.name == other.name:
return True
else:
return False
即可。
__hash__
在hash()一個類的時候,就會執行__hash__方法。就不多說了。