­

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__方法。就不多說了。