前言
python內部有許多內建裝飾器,它們都有特別的功能,下面對其歸納一下。
系列文章
python自帶裝飾器
staticmethod
staticmethod裝飾器的功能是去除類的方法默認第一個參數是類的實例,使得該方法成為一個普通的函數,staticmethod是一個類,屬於類裝飾器。
class Person(object):
def eat(self):
print('eat thing')
@staticmethod
def go(): # 不再傳遞self
print('go')
classmethod
類定義時,除了new方法外,其他定義的方法在調用時第一個參數傳入的必須是一個實例,使用classmethod裝飾器裝飾后,方法的第一個參數是類對象;調用類方法不需要創建類的實例。classmethod也是一個類,所以classmethod是一個類裝飾器。
class Person(object):
_num_ear = 2
def eat(self):
print('eat thing')
@classmethod
def go(cls):
print(cls._num_ear)
print('go')
if __name__ == '__main__':
Person.go() # 無需創建實例,直接調用。
property
對於一個類的屬性,python的訪問是沒有限制的,但有時候我們需要對屬性的訪問加以限制,property裝飾器就是干這個的。
property是一個類,它有三個方法,deleter,setter,getter,有兩種使用方式。
class Person(Animal):
_num_ear = 2
def __init__(self):
self._name = 'xiaoming'
self.age = 20
def get_name(self):
print('get name')
return self._name
def set_name(self, name):
print('set name')
self._name = name
def delete_name(self):
print('del name')
del self._name
name = property(get_name, set_name, delete_name, doc='name of person')
# 或使用匿名函數
name = property(lambda self:self._name, lambda self, name: setattr(self, '_name', name), lambda self:delattr(self,'_name'))
if __name__ == '__main__':
p = Person()
print(p.name) # 會調用get_name
p.name = 'xxxx' # 會調用set_name
del p.name # 會調用delete_name
property可以手動指定限制的函數,有四個參數,但是這樣顯得比較麻煩,可以使用裝飾器的形式。
class Person(Animal):
_num_ear = 2
@property
def name(self):
return self._name
@name.setter
def name(self, nm):
self._name = nm
@name.deleter
def name(self):
del self._name
if __name__ == '__main__':
p = Person()
print(p.name)
p.name = 'xxxx'
del p.name
一個函數被property裝飾后返回的是property對象,只有fget參數的函數可以被property,因為裝飾器只接受一個參數;另外的屬性設置和刪除需要直觀調用響應的方法。
abstractmethod
python的抽象類和java不一樣,java的抽象類不能實例化,同時抽象方法子類必須實現,否則報錯!但是python抽象類默認是可以實例化的,也可以這樣說,如果我們對抽象類定義:本身不能實例化,子類必須實現抽象方法;那么我們一般寫的基類都不是抽象類。如果想要實現java中的抽象類的效果該怎么辦呢?使用abstractmethod裝飾器,含義是抽象方法。
一個類中的任何方法被abstractmethod裝飾后,這個類不能實例化並且子類必須實現被abstractmethod裝飾的方法。
from abc import abstractmethod,ABCMeta
class Animal(metaclass=ABCMeta):
@abstractmethod
def eat(self):
pass
class Person(Animal):
_num_ear = 2
def eat(self):
print('eat thing')
@classmethod
def go(cls):
print(cls._num_ear)
print('go')
如果需要定義一個類是抽象類,那么它需要繼承ABCMeta而不是object,這樣abstractmethod裝飾器才會起作用。其起作用的原理是將一個方法的__isabstractmethod__屬性設置為True,這樣解釋器就會檢查子類是否實現了抽象方法。
總結
-
staticmethod裝飾器用來去掉類定義的方法默認傳入的第一個參數;
-
classmethod裝飾器用來改變類定義的方法的默認第一個參數,將實例對象改成類對象;
-
property裝飾器用來限制調用者對對象屬性的訪問;
-
abstractmethod裝飾器設置子類必須實現父類的抽象方法;
-
參考
