python---之cls,和self

zxyhhjs2017發表於2018-05-26
作者:秦風
 轉載:連結:https://www.zhihu.com/question/49660420/answer/335991541
來源:知乎
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。

一般來說,要使用某個類的方法,需要先例項化一個物件再呼叫方法。

而使用@staticmethod或@classmethod,就可以不需要例項化,直接類名.方法名()來呼叫。

這有利於組織程式碼,把某些應該屬於某個類的函式給放到那個類裡去,同時有利於名稱空間的整潔。

class A(object):
    a = 'a'
    @staticmethod
    def foo1(name):
        print 'hello', name
    def foo2(self, name):
        print 'hello', name
    @classmethod
    def foo3(cls, name):
        print 'hello', name

首先定義一個類A,類A中有三個函式,foo1為靜態函式,用@staticmethod裝飾器裝飾,這種方法與類有某種關係但不需要使用到例項或者類來參與。如下兩種方法都可以正常輸出,也就是說既可以作為類的方法使用,也可以作為類的例項的方法使用。

a = A()
a.foo1('mamq') # 輸出: hello mamq
A.foo1('mamq')# 輸出: hello mamq

foo2為正常的函式,是類的例項的函式,只能通過a呼叫。

a.foo2('mamq') # 輸出: hello mamq
A.foo2('mamq') # 報錯: unbound method foo2() must be called with A instance as first argument (got str instance instead)

foo3為類函式,cls作為第一個引數用來表示類本身. 在類方法中用到,類方法是隻與類本身有關而與例項無關的方法。如下兩種方法都可以正常輸出。

a.foo3('mamq') # 輸出: hello mamq
A.foo3('mamq') # 輸出: hello mamq

但是通過例子發現staticmethod與classmethod的使用方法和輸出結果相同,再看看這兩種方法的區別。

既然@staticmethod和@classmethod都可以直接類名.方法名()來呼叫,那他們有什麼區別呢
從它們的使用上來看,
@staticmethod不需要表示自身物件的self和自身類的cls引數,就跟使用函式一樣。
@classmethod也不需要self引數,但第一個引數需要是表示自身類的cls引數。
如果在@staticmethod中要呼叫到這個類的一些屬性方法,只能直接類名.屬性名或類名.方法名。
而@classmethod因為持有cls引數,可以來呼叫類的屬性,類的方法,例項化物件等,避免硬編碼。

也就是說在classmethod中可以呼叫類中定義的其他方法、類的屬性,但staticmethod只能通過A.a呼叫類的屬性,但無法通過在該函式內部呼叫A.foo2()。修改上面的程式碼加以說明:

class A(object):
    a = 'a'
    @staticmethod
    def foo1(name):
        print 'hello', name
        print A.a # 正常
        print A.foo2('mamq') # 報錯: unbound method foo2() must be called with A instance as first argument (got str instance instead)
    def foo2(self, name):
        print 'hello', name
    @classmethod
    def foo3(cls, name):
        print 'hello', name
        print A.a
        print cls().foo2(name)


總結:其實就是staticmethod,這個方法,不能在類內呼叫其他的類的方法
      而classmethod可以呼叫其他的方法,因為有cls這個引數。
     staticmethod 與classmethod的方法與self這個方法的區別,就是self必須使用例項化物件,也就是a=A(),a.方法()
     而另外兩個方法只用,A.方法()即可 

相關文章