1. 程式人生 > >python內部裝飾器@classmethod, @staticmethod, @property

python內部裝飾器@classmethod, @staticmethod, @property

python面向物件程式設計中經常會用到三個裝飾器語法:@classmethod, @staticmethod, @property。因為之前學習了下裝飾器,所以在此瞭解一下python內建的三個裝飾器。

@staticmethod和@classmethod

面向物件中類的方法一般有例項方法和靜態方法兩種,例項方法的呼叫需要先建立類的例項物件,而靜態方法可以直接可以通過類名來呼叫。在python中使用@staticmethod或@classmethod,就可以不需要例項化呼叫方法,從而達到靜態方法的效果(其實靜態方法又稱為類方法,python的這兩個裝飾器翻譯過來恰好對應這一概念的兩個名稱)。
靜態方法利於組織程式碼,把某些應該屬於某個類的函式放到那個類裡去,同時有利於名稱空間的整潔。
雖然@staticmethod和@classmethod都可以達到靜態方法的效果,但它們也存在著一些區別。
在使用時:
@staticmethod不需要像其他例項方法那樣新增一個表示自身物件的self引數。這個很像我們平時所說的靜態方法。
@classmethod也不需要self引數,但需要一個表示自身類的cls引數。因為持有這個cls引數,該裝飾器下的方法可以來呼叫類的屬性、方法,例項化物件等。更重要的也是區別與在函式內部直接使用類名呼叫自身類的方式在於,有了cls引數,當進行類的繼承時,cls會變成子類本身,避免了

硬編碼,而使用類名呼叫自身類會在繼承時無法更新到子類。
下面提供一個使用這兩個裝飾器的例項,程式碼如下:

class Obj(object):
    bar = 1

    def foo(self):
        print('foo')
    def from_j(self, p):
        Obj.foo()

    @staticmethod
    def static_foo():
        print('static_foo')
        print(Obj.bar)

    @classmethod
    def class_foo(cls)
:
print('class_foo') print(cls.bar) cls().foo() print('class_static_foo') cls.static_foo() Obj.static_foo() Obj.class_foo() ''' static_foo 1 class_foo 1 foo class_static_foo static_foo 1 '''

這裡有個StackOverflow問題深入地討論了@classmethod和@staticmethod的含義。

@property

這個裝飾器的作用一句話來概括就是把類中一個方法變成屬性呼叫。如下例:

class Student(object):

    @property
    def score(self):
        return self._score

    @score.setter
    def score(self, value):
        if not isinstance(value, int):
            raise ValueError('score must be an integer!')
        if value < 0 or value > 100:
            raise ValueError('score must between 0 ~ 100!')
        self._score = value

s = Student()
s.score = 60 # 實際轉化為s.set_score(60),增加了引數檢查
s.score # 實際轉化為s.get_score()

由上例可見,將一個類的方法變成屬性,只需要加上@property就可以了。同時與其配套使用的是裝飾器@score.setter,負責把一個setter方法變成屬性賦值。如果想要這個屬性是隻讀的,則可以省略@score.setter。
通過這種方式,可以用簡短的程式碼,封裝類內部的屬性,既沒有改變外部訪問普通屬性的方式,同時保證對引數進行必要的檢查,這樣,程式執行時就減少了出錯的可能性。