魔法方法總結(jié)
字符串/字節(jié)序列表示相關(guān):__repr__、__str__,__format__,__bytes__。這些主要是做一些格式化的操作。
數(shù)值轉(zhuǎn)換:__abs__、__bool__、__complex__、__int__、__float__、__hash__、__index__。
集合模擬:__len__、__getitem__、__setitem__、__delitem__、__contains__。用的列表就包括了這些方法。
迭代枚舉:__iter__、__reversed__、__next__。主要用于迭代器和生成器。
可調(diào)用模擬:__call__。主要是加上括號就能觸發(fā)調(diào)用。
上下文管理:__enter__、__exit__。大家還記得with讀取文件嗎,其實(shí)就是上下文管理器。
實(shí)例創(chuàng)建和銷毀:__new__、__init__、__del__。這些都是創(chuàng)建類中常常使用的。
屬性相關(guān):__getattribute__、__getattr__、__setattr__、__delattr__、__setattr__、__dir__。這五個(gè)方法主要是用于操作屬性的。
屬性描述符:__get__、__set__、__del__。用來定義屬性描述符。
方法重寫
如果父類方法的功能不能滿足需求,可以在子類重寫父類的方法,實(shí)例如下:
class Parent: #定義父類 def myMethod(self): print(‘調(diào)用父類方法’) class Child(Parent): #定義子類 def myMethod(self): print(‘調(diào)用子類方法’) c=Child() #子類實(shí)例c.myMethod() #子類調(diào)用重寫方法super(Child,c).myMethod() #用子類對象調(diào)用父類已被覆蓋的方法#super()是用于調(diào)用父類(超類)的一個(gè)方法。#調(diào)用子類方法#調(diào)用父類方法
魔法方法
在Python中,有一些內(nèi)置好的特定的方法,這些方法在進(jìn)行特定的操作時(shí)會(huì)自動(dòng)被調(diào)用,稱之為魔法方法,下面介紹幾種常見的魔法方法。
- __ new__(cls[,* argv])
- __ new__ 是在一個(gè)對象實(shí)例化的時(shí)候所調(diào)用的第一個(gè)方法,它的第一個(gè)參數(shù)是這個(gè)類,其他的參數(shù)是用來直接傳遞給 __ init__ 方法
- __ new__ 決定是否要使用該 __ init__ 方法,因?yàn)?__ new__ 可以調(diào)用其他類的構(gòu)造方法或者直接返回別的實(shí)例對象來作為本類的實(shí)例,如果 __ new__ 沒有返回實(shí)例對象,則 __ init__ 不會(huì)被調(diào)用
- __ new__ 主要是用于繼承一個(gè)不可變的類型比如一個(gè) tuple 或者 string
- cls:代表一個(gè)類的名稱
- self:代表一個(gè)實(shí)例對象的名稱
class myMethod(str): def __new__(cls,string): string=string.upper() return str.__new__(cls,string) X=myMethod(‘DataScience’)print(X)#DATASCIENCE
__ init__:
初始化函數(shù),在創(chuàng)建實(shí)例對象為其賦值時(shí)使用,在__ new__ 之后,__ init __ 必須至少有一個(gè)參數(shù)self,就是這個(gè) __ new__ 返回的實(shí)例,__ init__ 是在 __ new__ 的基礎(chǔ)上可以完成一些其它初始化的動(dòng)作,__ init__不需要返回值。
class Dog: def __init__(self,color,brand): self.color=color self.brand=brandpuppy=Dog(‘黑色’,’拉布拉多’)print(puppy)#
下面再來一個(gè)結(jié)合__ init__ 和__ new__兩個(gè)魔法方法的例子:
class A(object): passclass B(A): def __init__(self): print(‘__init__被調(diào)用’) def __new__(cls): print(‘__new__被調(diào)用’) print(id(cls)) return object.__new__(A) #注意此處采用了參數(shù)A而不是cls,__new__沒有正確返回當(dāng)前類cls的實(shí)例b=B()print(b)print(type(b)) #類型所繼承的基類print(id(A))print(id(B))”’__new__被調(diào)用281212608576828121260838802812126085768”’
從運(yùn)行結(jié)果可以看出,__ new__ 中的參數(shù)cls和B的id是相同的,表明__ new__ 中默認(rèn)的參數(shù)cls就是B類本身,而在return時(shí),并沒有正確返回當(dāng)前類cls的實(shí)例,而是返回了其父類A的實(shí)例,因此__ init__這一魔法方法并沒有被調(diào)用,此時(shí)__ new__雖然是寫在B類中的,但其創(chuàng)建并返回的是一個(gè)A類的實(shí)例對象。
現(xiàn)在將return中的參數(shù)A變?yōu)閏ls,再來看一下運(yùn)行結(jié)果:
class A(object): passclass B(A): def __init__(self): print(‘__init__被調(diào)用’) def __new__(cls): print(‘__new__被調(diào)用’) print(id(cls)) return object.__new__(cls) #注意此處采用了參數(shù)A而不是cls,__new__沒有正確返回當(dāng)前類cls的實(shí)例b=B()print(b)print(type(b)) #類型所繼承的基類print(id(A))print(id(B))”’__new__被調(diào)用2812126087656__init__被調(diào)用28121260867122812126087656”’
可以看出,當(dāng)__ new__ 正確返回其當(dāng)前類cls的實(shí)例對象時(shí),__ init__被調(diào)用了,此時(shí)創(chuàng)建并返回的是一個(gè)B類的實(shí)例對象。
__ class__:
獲得已知對象的類 ( 對象.__ class__)。
基礎(chǔ)格式如下:
class My: passa=A()print(a.__class__)#
__ class__在下面這種情況中是有用的:即當(dāng)一個(gè)類中的某個(gè)成員變量是所有該類的對象的公共變量時(shí).
下面看一個(gè)例子:
class My: count=0 def addcount(self): self.__class__.count +=1 a=My()a.addcount()print(a.count)print(‘*’*50)b=My()b.addcount()print(b.count)#1#**************************************************#2
從運(yùn)行結(jié)果可以看出,雖然a和b是兩個(gè)不同的My類的實(shí)例對象,但采用了__ class__ 之后,分別調(diào)用兩個(gè)對象的addcount方法之后,獲取到的對象的count屬性卻是在不斷累加的,此時(shí)self.__ class__ .count不再是單純的某個(gè)對象私有的屬性,而是類的所有實(shí)例對象的共有屬性,它相當(dāng)于self.A.count。若將self.__ class__ .count += 1變?yōu)閟elf.count += 1,此時(shí)__ class__的效果就十分明顯了。
class My: count=0 def addcount(self): self.count +=1 a=My()a.addcount()print(a.count)print(‘*’*50)b=My()b.addcount()print(b.count)#1#**************************************************#1
__ str__:
在將對象轉(zhuǎn)換成字符串 str(對象) 測試的時(shí)候,打印對象的信息,__ str__ 方法必須要return一個(gè)字符串類型的返回值,作為對實(shí)例對象的字符串描述,__ str__ 實(shí)際上是被print函數(shù)默認(rèn)調(diào)用的,當(dāng)要print(實(shí)例對象)時(shí),默認(rèn)調(diào)用__ str__ 方法,將其字符串描述返回。如果不是要用str()函數(shù)轉(zhuǎn)換。當(dāng)打印一個(gè)類的時(shí)候,那么print首先調(diào)用的就是類里面的定義的__ str__。
class My(): def __init__(self,name): self.name=name def __str__(self): return(‘我是My類的實(shí)例對象my,我的名字叫%s’%self.name) my=My(‘小王’)print(My)print(my)##我是My類的實(shí)例對象my,我的名字叫小王
類的專有方法
- __ init__ : 構(gòu)造函數(shù),在生成對象時(shí)調(diào)用
- __ del__ : 析構(gòu)函數(shù),釋放對象時(shí)使用
- __ repr__ : 打印,轉(zhuǎn)換
- __ setitem__ : 按照索引賦值
- __ getitem__: 按照索引獲取值
- __ len__ : 獲得長度
- __ cmp__ : 比較運(yùn)算
- __ call__ : 函數(shù)調(diào)用
- __ add__ : 加運(yùn)算
- __ sub__ : 減運(yùn)算
- __ mul__ : 乘運(yùn)算
- __ truep__ : 除運(yùn)算
- __ mod__ : 求余運(yùn)算
- __ pow__ : 乘方
總結(jié)
- 修改類方法和屬性,會(huì)影響實(shí)例方法和屬性
- 一個(gè)實(shí)例屬性的修改,不會(huì)影響另一個(gè)實(shí)例屬性
- 類方法可以修改,但實(shí)例方法不允許修改