python教程:类的装饰器方法、特殊成员方法
裝飾器方法
類的另外的特性,裝飾器方法:靜態(tài)方法(staticmethod)、類方法(classmethod)、屬性方法(property)
1、靜態(tài)方法
在方法名前加上@staticmethod裝飾器,表示此方法為靜態(tài)方法
class Dog(object):def __init__(self, name):self.name = name@staticmethod # 在方法前加上staticmethod 裝飾器定義靜態(tài)方法def eat():print("dog is eating")靜態(tài)方法特性
特性:只是名義上歸類管理,實(shí)際上在靜態(tài)方法里訪問不了類或?qū)嵗械娜魏螌傩?/p>
靜態(tài)方法,是不可以傳入self參數(shù)的,但是想傳也可以,調(diào)用時(shí)必須傳入實(shí)例本身
class Dog(object):def __init__(self, name):self.name = name@staticmethod # 定義靜態(tài)方法def eat(self, food): # 可以定義,但是需傳入實(shí)例本身print("{0} is eating {1}".format(self.name, food))d = Dog("shabi") d.eat(d, "hotdog") # 傳入實(shí)例d本身,否則會(huì)報(bào)錯(cuò)# 輸出 shabi is eating hotdog靜態(tài)方法可以用類直接調(diào)用,直接調(diào)用時(shí),不可以直接傳入self,否則會(huì)報(bào)錯(cuò)
''' 遇到問題沒人解答?小編創(chuàng)建了一個(gè)Python學(xué)習(xí)交流QQ群:778463939 尋找有志同道合的小伙伴,互幫互助,群里還有不錯(cuò)的視頻學(xué)習(xí)教程和PDF電子書! ''' class Dog(object):def __init__(self,name):self.name = name@staticmethoddef eat(food):print("is eating {0}".format(food))Dog.eat("hotdog")#輸出 is eating hotdog靜態(tài)方法的使用場(chǎng)景,這種場(chǎng)景挺常見,就像os模塊的中某些函數(shù)一樣,都是使用了靜態(tài)方法
import osos.system() os.mkdir()2、類方法
在方法名前加上@classmethod裝飾器,表示此方法為類方法
class Dog(object):name = "honggege" #定義靜態(tài)屬性def __init__(self,name):self.name = name@classmethod #定義類方法def eat(self,food):print("{0} is eating {1}".format(self.name,food))類方法特性
特性:只能訪問類變量(又叫靜態(tài)屬性),不能訪問實(shí)例變量
''' 遇到問題沒人解答?小編創(chuàng)建了一個(gè)Python學(xué)習(xí)交流QQ群:778463939 尋找有志同道合的小伙伴,互幫互助,群里還有不錯(cuò)的視頻學(xué)習(xí)教程和PDF電子書! ''' class Dog(object):def __init__(self, name):self.name = name@classmethod # 定義類方法def eat(self, food):print("{0} is eating {1}".format(self.name, food))d = Dog("shabihong") d.eat("hotdog")# 輸出 Traceback (most recent call last):d.eat("hotdog")print("{0} is eating {1}".format(self.name, food)) AttributeError: type object 'Dog' has no attribute 'name'訪問類變量(又叫靜態(tài)屬性)
class Dog(object):name = "honggege" #定義類變量def __init__(self,name):self.name = name@classmethoddef eat(self,food):print("{0} is eating {1}".format(self.name,food))d = Dog("shabihong") d.eat("hotdog")#輸出 honggege is eating hotdog #調(diào)用的是類變量使用場(chǎng)景:一般是需要去訪問寫死的變量,才會(huì)用到類方法裝飾器
3、屬性方法
在方法名前加上@property裝飾器,表示此方法為屬性方法
class Dog(object):def __init__(self,name):self.name = name@property #定義屬性方法def eat(self):print("{0} is eating".format(self.name))屬性方法特性
特性:把一個(gè)方法變成一個(gè)靜態(tài)屬性
靜態(tài)屬性的調(diào)用
''' 遇到問題沒人解答?小編創(chuàng)建了一個(gè)Python學(xué)習(xí)交流QQ群:778463939 尋找有志同道合的小伙伴,互幫互助,群里還有不錯(cuò)的視頻學(xué)習(xí)教程和PDF電子書! ''' class Dog(object):def __init__(self,name):self.name = name@property #定義屬性方法def eat(self):print("{0} is eating".format(self.name))d = Dog("shabihong") d.eat #把方法變成靜態(tài)屬性調(diào)用#輸出 shabihong is eating給轉(zhuǎn)成的靜態(tài)屬性賦值
用@靜態(tài)方法名.setter(屬性裝飾器)去裝飾方法,來(lái)給轉(zhuǎn)換后的靜態(tài)屬性賦值
class Dog(object):def __init__(self,name):self.name = name@property #定義屬性方法def eat(self):print("{0} is eating {1}".format(self.name,"honggege"))@eat.setter #定義一個(gè)可以傳參的方法def eat(self,food):print("set to food:",food)# self.__food = foodd = Dog("shabihong") d.eat = "hotdog" #給轉(zhuǎn)成的靜態(tài)變量賦值 d.eat#輸出 set to food: hotdog shabihong is eating honggege上面代碼沒有把food傳上去,那是因?yàn)閭鲄⒎椒?#xff0c;沒有把接收之前的food的賦值,修改成如下代碼就能成功上傳:
class Dog(object):def __init__(self,name):self.name = nameself.__food = None@property #定義屬性方法def eat(self):print("{0} is eating {1}".format(self.name,self.__food))@eat.setter #定義可以設(shè)置變量賦值def eat(self,food):print("set to food:",food)self.__food = foodd = Dog("shabihong") d.eat #第一份賦值的是None d.eat = "hotdog" d.eat #第二個(gè)賦值是hotdog#輸出 shabihong is eating None set to food: hotdog shabihong is eating hotdog #說(shuō)明賦值成功刪除轉(zhuǎn)變的靜態(tài)屬性
用@靜態(tài)方法名.deleter(屬性裝飾器)去裝飾,表明可以刪除轉(zhuǎn)化后的靜態(tài)屬性
''' 遇到問題沒人解答?小編創(chuàng)建了一個(gè)Python學(xué)習(xí)交流QQ群:778463939 尋找有志同道合的小伙伴,互幫互助,群里還有不錯(cuò)的視頻學(xué)習(xí)教程和PDF電子書! ''' class Dog(object):def __init__(self,name):self.name = nameself.__food = None@propertydef eat(self):print("{0} is eating {1}".format(self.name,self.__food))@eat.setterdef eat(self,food):print("set to food:",food)self.__food = food@eat.deleter #定義可以刪除eat這個(gè)靜態(tài)屬性def eat(self):del self.__foodprint("food 變量刪除完畢")d = Dog("shabihong") del d.eat #刪除靜態(tài)屬性eat#輸出 food 變量刪除完畢靜態(tài)屬性使用場(chǎng)景
一個(gè)航班當(dāng)前的狀態(tài),是到達(dá)了、延遲了、取消了、還是已經(jīng)飛走了, 想知道這種狀態(tài)必須經(jīng)歷以下幾步:
因此這個(gè)status屬性的值是一系列動(dòng)作后才得到的結(jié)果,所以你每次調(diào)用時(shí),其實(shí)它都要經(jīng)過(guò)一系列的動(dòng)作才返回你結(jié)果,但這些動(dòng)作過(guò)程不需要用戶關(guān)心, 用戶只需要調(diào)用這個(gè)屬性就可以
class Flight(object):def __init__(self,name):self.flight_name = namedef checking_status(self):print("checking flight %s status " % self.flight_name)return 1@propertydef flight_status(self):status = self.checking_status()if status == 0 :print("flight got canceled...")elif status == 1 :print("flight is arrived...")elif status == 2:print("flight has departured already...")else:print("cannot confirm the flight status...,please check later")@flight_status.setter #修改def flight_status(self,status):status_dic = {0 : "canceled",1 :"arrived",2 : "departured"}print("\033[31;1mHas changed the flight status to \033[0m",status_dic.get(status) )@flight_status.deleter #刪除def flight_status(self):print("status got removed...")f = Flight("CA980") f.flight_status f.flight_status = 2 #觸發(fā)@flight_status.setter del f.flight_status #觸發(fā)@flight_status.deleter裝飾器方法總結(jié):
類的特殊成員方法
類的方法,有普通方法,就是我們自己定義的方法,還有裝飾器方法(靜態(tài)方法,類方法,屬性方法),其實(shí)類還有另外一種方法,叫做類的特殊成員方法
1、 __doc__
說(shuō)明:表示類的描述信息
''' 遇到問題沒人解答?小編創(chuàng)建了一個(gè)Python學(xué)習(xí)交流QQ群:778463939 尋找有志同道合的小伙伴,互幫互助,群里還有不錯(cuò)的視頻學(xué)習(xí)教程和PDF電子書! ''' class Dog(object):"""此類是形容Dog這個(gè)類""" #類的描述信息def __init__(self,name):self.name = nameprint(Dog.__doc__) #打印類的描述信息#輸出 此類是形容Dog這個(gè)類2、 __module__和__class__
說(shuō)明:
- __module__: 表示當(dāng)前操作的對(duì)象在哪個(gè)模塊
- __class__:表示當(dāng)前操作的對(duì)象的類是什么
3 、__init__
說(shuō)明:構(gòu)造方法,通過(guò)類創(chuàng)建對(duì)象時(shí),自動(dòng)觸發(fā)執(zhí)行
4、 __del__
注:此方法一般無(wú)須定義,因?yàn)镻ython是一門高級(jí)語(yǔ)言,程序員在使用時(shí)無(wú)需關(guān)心內(nèi)存的分配和釋放,因?yàn)榇斯ぷ鞫际墙唤oPython解釋器來(lái)執(zhí)行,所以,析構(gòu)函數(shù)的調(diào)用是由解釋器在進(jìn)行垃圾回收時(shí)自動(dòng)觸發(fā)執(zhí)行的
說(shuō)明:析構(gòu)方法,當(dāng)對(duì)象在內(nèi)存中被釋放時(shí),自動(dòng)觸發(fā)執(zhí)行
5、 __call__
注:構(gòu)造方法的執(zhí)行是由創(chuàng)建對(duì)象觸發(fā)的,即:對(duì)象 = 類名() ;而對(duì)于 __call__方法的執(zhí)行是由對(duì)象后加括號(hào)觸發(fā)的,即:對(duì)象() 或者 類()()
說(shuō)明: 對(duì)象后面加括號(hào),觸發(fā)執(zhí)行
''' 遇到問題沒人解答?小編創(chuàng)建了一個(gè)Python學(xué)習(xí)交流QQ群:778463939 尋找有志同道合的小伙伴,互幫互助,群里還有不錯(cuò)的視頻學(xué)習(xí)教程和PDF電子書! ''' class Foo(object):def __init__(self):self.name = "shuaigaogao"def __call__(self, *args, **kwargs): #重寫call方法print("running call",args,kwargs)f = Foo() #執(zhí)行__init__ f(1,2,3,name=333) # 執(zhí)行call方法,也可以寫成 Foo()(1,2,3,name=333)#輸出 running call (1, 2, 3) {'name': 333}6 、__dict__
說(shuō)明: 查看類或?qū)ο笾械乃谐蓡T
①類.__dict__
效果:打印類中所有的屬性,不包括實(shí)例屬性
class Province(object):country = 'China'def __init__(self, name, count):self.name = nameself.count = countdef func(self, *args, **kwargs):print("func")print(Province.__dict__) #類.__dict__#輸出 {'__module__': '__main__', 'country': 'China', '__init__': <function Province.__init__ at 0x033D5C00>, 'func': <function Province.func at 0x033D5AE0>, '__dict__': <attribute '__dict__' of 'Province' objects>, '__weakref__': <attribute '__weakref__' of 'Province' objects>, '__doc__': None} #打印類中所有的屬性,不包括實(shí)例屬性②實(shí)例名.__dict__
效果:打印該實(shí)例的所有屬性,不包括類屬性
class Province(object):country = 'China'def __init__(self, name, count):self.name = nameself.count = countdef func(self, *args, **kwargs):print("func")p = Province("jiangsu",20000) #實(shí)例化 print(p.__dict__) #實(shí)例名.__dict__#輸出 {'count': 20000, 'name': 'jiangsu'} #打印該實(shí)例的所有屬性,不包括類屬性7 、__str__
說(shuō)明:如果一個(gè)類中定義了__str__方法,那么在打印 對(duì)象 時(shí),默認(rèn)輸出該方法的返回值
''' 遇到問題沒人解答?小編創(chuàng)建了一個(gè)Python學(xué)習(xí)交流QQ群:778463939 尋找有志同道合的小伙伴,互幫互助,群里還有不錯(cuò)的視頻學(xué)習(xí)教程和PDF電子書! ''' class Province(object):country = 'China'def __init__(self, name):self.name = namedef __str__(self):return "<obj:{0}>".format(self.name)p = Province("jiangsu") print(p) #打印這個(gè)對(duì)象#輸出 <obj:jiangsu> #給對(duì)象重新起了一個(gè)名字注:這個(gè)會(huì)在django框架里面會(huì)用到
8 、__getitem__、__setitem__、__delitem__
說(shuō)明:用于索引操作,如字典。以上分別表示獲取、設(shè)置、刪除數(shù)據(jù)
class Foo(object):def __getitem__(self, key):print('__getitem__:',key)def __setitem__(self, key, value):print('__setitem__:',key,value)def __delitem__(self, key):print('__delitem__',key)f = Foo() f["name"] = "shuaigaogao" #自動(dòng)觸發(fā)__setitem__方法 f["name"] #自動(dòng)觸發(fā)__getitem__方法 del f["name"] #自動(dòng)觸發(fā)__delitem__方法#輸出 __setitem__: name shuaigaogao __getitem__: name __delitem__ name注:這邊的__delitem__沒有做真正的刪除,只是觸發(fā)這個(gè)方法,想要真正刪除,只需要在__delitem__函數(shù)中添加刪除功能即可
9、__new__ \ __metaclass__
__new__概念
new方法是類自帶的一個(gè)方法,可以重構(gòu),__new__方法在實(shí)例化的時(shí)候也會(huì)執(zhí)行,并且先于__init__方法之前執(zhí)行
''' 遇到問題沒人解答?小編創(chuàng)建了一個(gè)Python學(xué)習(xí)交流QQ群:778463939 尋找有志同道合的小伙伴,互幫互助,群里還有不錯(cuò)的視頻學(xué)習(xí)教程和PDF電子書! ''' class Foo(object):def __init__(self, name):self.name = nameprint("Foo __init__")def __new__(cls, *args, **kwargs):print("Foo __new__", cls, *args, **kwargs)return object.__new__(cls)f = Foo("shuaigaogao")# 輸出 Foo __new__ <class '__main__.Foo'> shuaigaogao Foo __init____new__方法作用
作用:所有對(duì)象都是通過(guò)new方法來(lái)實(shí)例化的,new里面調(diào)用了init方法,所以在實(shí)例化的過(guò)程中先執(zhí)行的是new方法,而不是init方法。
①重構(gòu)__new__方法
class Foo(object):def __init__(self,name):self.name = nameprint("Foo __init__")def __new__(cls, *args, **kwargs):print("Foo __new__",cls, *args, **kwargs)f = Foo("shuaigaogao") #實(shí)例化#輸出 Foo __new__ <class '__main__.Foo'> shuaigaogao由上面的例子看出,沒有執(zhí)行__init__方法
②重構(gòu)__new__方法,并繼承父類的__new__方法
class Foo(object):def __init__(self,name):self.name = nameprint("Foo __init__")def __new__(cls, *args, **kwargs): #cls相當(dāng)于傳入類Fooprint("Foo __new__",cls, *args, **kwargs)return object.__new__(cls) #繼承父類的__new__方法,這邊必須以返回值的形式繼承f = Foo("shuaigaogao")#輸出 Foo __new__ <class '__main__.Foo'> shuaigaogao由上面不難看出,大多數(shù)情況下,你都不要去重構(gòu)你的__new__方法,因?yàn)槟愀割愔幸呀?jīng)有__new__方法了,已經(jīng)幫你寫好了怎么去創(chuàng)建類,如果你重寫的話,就會(huì)覆蓋父類的里面的__new__方法。但是你重構(gòu)可以增加一點(diǎn)小功能,但是你覆蓋了以后還是需要繼承父類回來(lái),要不然你的這個(gè)實(shí)力就創(chuàng)建不了。
__new__使用場(chǎng)景
我想對(duì)我自己寫的一些類進(jìn)行定制,就在它實(shí)例化之前就進(jìn)行定制,就可以用到__new__方法,new方法就是用來(lái)創(chuàng)建實(shí)力的,重構(gòu)new方法,必須以返回值的形式繼承父類的new方法。
在創(chuàng)建對(duì)象時(shí)候,同時(shí)創(chuàng)建一個(gè)類變量
''' 遇到問題沒人解答?小編創(chuàng)建了一個(gè)Python學(xué)習(xí)交流QQ群:778463939 尋找有志同道合的小伙伴,互幫互助,群里還有不錯(cuò)的視頻學(xué)習(xí)教程和PDF電子書! ''' class Foo(object):def __init__(self,name):self.name = nameprint("Foo __init__")def __new__(cls, *args, **kwargs): #cls相當(dāng)于是傳入的類名Foocls.name = "shuaigaogao" #創(chuàng)建對(duì)象是定義靜態(tài)變量print(cls.name)return object.__new__(cls) #繼承父類的__new__方法f = Foo("shuaigaogao") print(Foo.name)#輸出 shuaigaogao Foo __init__ shuaigaogao__metaclass__
metaclass這個(gè)屬性叫做元類,它是用來(lái)表示這個(gè)類是由誰(shuí)來(lái)幫他實(shí)例化創(chuàng)建的,說(shuō)白了,就是相當(dāng)于自己定制一個(gè)類。
class MyType(type):def __init__(self,*args,**kwargs):print("Mytype __init__",*args,**kwargs)def __call__(self, *args, **kwargs):print("Mytype __call__", *args, **kwargs)obj = self.__new__(self)print("obj ",obj,*args, **kwargs)print(self)self.__init__(obj,*args, **kwargs)return objdef __new__(cls, *args, **kwargs):print("Mytype __new__",*args,**kwargs)return type.__new__(cls, *args, **kwargs)class Foo(object,metaclass=MyType): #python3統(tǒng)一用這種#__metaclass__ = MyType #python2.7中的寫法def __init__(self,name):self.name = nameprint("Foo __init__")def __new__(cls, *args, **kwargs):print("Foo __new__",cls, *args, **kwargs)return object.__new__(cls)f = Foo("shuaigaogao") print("f",f) print("fname",f.name)#輸出 Mytype __new__ Foo (<class 'object'>,) {'__new__': <function Foo.__new__ at 0x0000025EF0EFD6A8>, '__init__': <function Foo.__init__ at 0x0000025EF0EFD620>, '__qualname__': 'Foo', '__module__': '__main__'} Mytype __init__ Foo (<class 'object'>,) {'__new__': <function Foo.__new__ at 0x0000025EF0EFD6A8>,'__init__': <function Foo.__init__ at 0x0000025EF0EFD620>, '__qualname__': 'Foo', '__module__': '__main__'} Mytype __call__ shuaigaogao Foo __new__ <class '__main__.Foo'> obj <__main__.Foo object at 0x0000025EF0F05048> shuaigaogao <class '__main__.Foo'> Foo __init__ f <__main__.Foo object at 0x0000025EF0F05048> fname shuaigaogao創(chuàng)建過(guò)程如下:
類的生成 調(diào)用 順序依次是 __new__ --> __init__ --> __call__
總結(jié)
以上是生活随笔為你收集整理的python教程:类的装饰器方法、特殊成员方法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python教程:封装、多态、反射
- 下一篇: python教程:可变长参数(*args