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