一、靜態方法
1.1、定義
在類中的方法前面通過@staticmethod裝飾器即可把其裝飾的方法變為一個靜態方法
class Person(object): def __init__(self, name): self.name = name @staticmethod def speak(): print('someone is speaking chinese.') # 靜態方法在類中也不需要傳入 self參數
1.2、靜態方法的特性
靜態方法是不能訪問實例變量和類變量的
class Person(object): def __init__(self, name): self.name = name @staticmethod def speak(self): print('%s is speaking chinese.' % self.name) p = Person('Bigberg') p.speak() # 我們在 speak(self) 函數中傳入 self
事實上以上代碼運行會出錯的,說speak 需要一個self參數,但調用時卻沒有傳遞,沒錯,當speak變成靜態方法后,再通過實例調用時就不會自動把實例本身當作一個參數傳給self了。
Traceback (most recent call last): File "G:/python/untitled/study6/靜態方法.py", line 26, in <module> p.speak() TypeError: speak() missing 1 required positional argument: 'self'
想讓以上代碼可以正常執行,有兩種方法:
- 在調用時將實例本身傳給 speak()
class Person(object): def __init__(self, name): self.name = name @staticmethod def speak(self): print('%s is speaking chinese.' % self.name) p = Person('Bigberg') p.speak(p) # 輸出 Bigberg is speaking chinese.
2.在方法speak中去掉self,但這也意味着,在eat中不能通過self.調用實例中的其它變量了
class Person(object): def __init__(self, name): self.name = name @staticmethod def speak(): # 方法中已經沒有 self 參數了 print('%s is speaking chinese.' % 'anyone') p = Person('Bigberg') p.speak() #輸出 anyone is speaking chinese.
1.3 總結
普通的方法,可以在實例化后直接調用,並且在方法里可以通過self.調用實例變量或類變量,但靜態方法是不可以訪問實例變量或類變量的,一個不能訪問實例變量和類變量的方法,其實相當於跟類本身已經沒什么關系了,它與類唯一的關聯就是需要通過類名來調用這個方法。
二、類方法
2.1、定義
類方法通過@classmethod裝飾器實現,類方法和普通方法的區別是, 類方法只能訪問類變量,不能訪問實例變量
2.2、訪問實例變量
直接訪問實例變量會報錯,沒有該屬性
class Person(object): def __init__(self, name, country): self.name = name self.country = country @classmethod def nationality(self): print('Bigberg is %s.' % self.country) p = Person('Bigberg', 'CN') p.nationality() # 輸出 Traceback (most recent call last): File "G:/python/untitled/study6/靜態方法.py", line 31, in <module> p.nationality() File "G:/python/untitled/study6/靜態方法.py", line 24, in nationality print('Bigberg is %s.' % self.country) AttributeError: type object 'Person' has no attribute 'country' # 提示沒有一個 country 屬性
2.3、訪問類變量,即 全局屬性/靜態字段
class Person(object): country = 'Chinese' # 增加一個 全局屬性/靜態字段 def __init__(self, name, country): self.name = name self.country = country @classmethod def nationality(cls): # 這里將sefl 改為 cls print('Bigberg is %s.' % cls.country) p = Person('Bigberg', 'CN') p.nationality() # 輸出 Bigberg is Chinese.
三、屬性方法
3.1、定義
屬性方法的作用就是通過@property把一個方法變成一個靜態屬性
class Person(object): country = 'Chinese' def __init__(self, name, country): self.name = name self.country = country @property def drive(self): print('%s is driving a car.' % self.name)
p = Person('Bigberg', 'CN') p.drive()
# 輸出
Traceback (most recent call last): Bigberg is driving a car. File "G:/python/untitled/study6/靜態方法.py", line 38, in <module> p.drive() TypeError: 'NoneType' object is not callable
調用會出錯誤, 說NoneType is not callable, 因為eat此時已經變成一個靜態屬性了, 不是方法了, 想調用已經不需要加()號了,直接p.drive就可以了
正常調用:
p = Person('Bigberg', 'CN') p.drive # 輸出 Bigberg is driving a car.
3.2 setter用法
如果我們想在屬性方法里傳參,比如車的品牌,我們就要用setter了,具體用法 @屬性方法名.setter
class Person(object): country = 'Chinese' def __init__(self, name, country): self.name = name self.country = country self.car = "LAMBORGHINI" # 定義車品牌為蘭博基尼 @property def drive(self): print('%s is driving a %s.' % (self.name, self.car)) p = Person('Bigberg', 'CN') p.drive # 輸出 Bigberg is driving a LAMBORGHINI.
很顯然我們開出去的車就是蘭博基尼,如果我們想自己傳入車品牌呢?比如 特斯拉:
class Person(object): country = 'Chinese' def __init__(self, name, country): self.name = name self.country = country self.car = "LAMBORGHINI" #當然這里也可以設置為私有屬性 @property def drive(self): # 這里不能傳參是因為調用的時候,p.drive 沒有()了,不能傳入 print('%s is driving a %s.' % (self.name, self.car)) @drive.setter # 修飾方法drive,可以為屬性賦值 def drive(self, car): # 我們要重新定義這個drive方法 print("set car:", car) self.car = car p = Person('Bigberg', 'CN') p.drive = 'Tesla' # 給屬性賦值 p.drive #輸出 set car: Tesla Bigberg is driving a Tesla.
3.3 deleter 用法
用來刪除屬性方法,具體用法 @屬性方法名.deleter
# 以上例 # 我們可以發現普通屬性是可以通過del直接刪除的 # 比如 print(p.name) del p.name print(p.name) # 輸出 Traceback (most recent call last): Bigberg File "G:/python/untitled/study6/靜態方法.py", line 49, in <module> print(p.name) AttributeError: 'Person' object has no attribute 'name' #刪除之后就不能再調用了
但是我們用del p.drive這種方法來刪除屬性方法是行不通的:
del p.drive #輸出 Traceback (most recent call last): File "G:/python/untitled/study6/靜態方法.py", line 51, in <module> del p.drive AttributeError: can't delete attribute
所以我們就要用到 deleter方法:
class Person(object): country = 'Chinese' def __init__(self, name, country): self.name = name self.country = country self.car = "LAMBORGHINI" @property def drive(self): print('%s is driving a %s.' % (self.name, self.car)) @drive.setter def drive(self, car): print("set car:", car) self.car = car @drive.deleter # 修飾 drive 方法,可以刪除屬性 def drive(self): # 重新定義 drive方法 del self.car # 刪除的是屬性 print("扣了你的車,讓你開豪車...") p.drive = 'Tesla' p.drive del p.drive # 輸出 set car: Tesla Bigberg is driving a Tesla. 扣了你的車,讓你開豪車...
讓我們在秋名山再開一次車...
p.drive # 輸出 扣了你的車,讓你開豪車... Traceback (most recent call last): File "G:/python/untitled/study6/靜態方法.py", line 57, in <module> p.drive File "G:/python/untitled/study6/靜態方法.py", line 28, in drive print('%s is driving a %s.' % (self.name, self.car)) AttributeError: 'Person' object has no attribute 'car' # 提示沒有這個屬性了
四、屬性方法應用場景
你想知道一個航班當前的狀態,是到達了、延遲了、取消了、還是已經飛走了, 想知道這種狀態你必須經歷以下幾步:
1. 連接航空公司API查詢
2. 對查詢結果進行解析
3. 返回結果給你的用戶
因此這個status屬性的值是一系列動作后才得到的結果,所以你每次調用時,其實它都要經過一系列的動作才返回你結果,但這些動作過程不需要用戶關心,用戶只要知道結果就行
class Flight(object): def __init__(self, name): self.name = name def check_status(self): print("checking flight %s status" % self.name) return 1 @property def flight_status(self): status = self.check_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") @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 #輸出 checking flight CA980 status flight is arrived... Has changed the flight status to departured
五、總結
- 靜態方法是不可以訪問實例變量或類變量的
- 類方法和普通方法的區別是, 類方法只能訪問類變量,不能訪問實例變量
- 屬性方法將一個方法變為類的屬性,調用時不需要加()。有@property 、@屬性方法名.setter、@屬性方法名.deleter 三種裝飾方法