一、靜態方法
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 三種裝飾方法
