Python常見面試題006 類方法、類實體方法、靜態方法有何區別?

2023-02-25 09:00:21

006. Python中類方法、類實體方法、靜態方法有何區別?

全部放一個裡面篇幅過大了,就拆分成1個個釋出

範例程式碼

class Human:
    def __init__(self, name):
        self.name = name

    def say(self):
        print(f'我的名字是{self.name}')

    @classmethod
    def walk(self):
        print('類方法 walk')

    @staticmethod
    def sleep():
        print('類靜態方法 sleep')

一般這樣呼叫

# 類名.類方法
Human.walk()

# 範例名.實體方法
wuxianfeng = Human('wuxianfeng')
wuxianfeng.say()

# 靜態方法則無所謂
Human.sleep()
wuxianfeng.sleep()

問題就是,範例能否呼叫類方法?類能否呼叫實體方法呢?

  • 範例能否呼叫類方法:能,比如wuxianfeng.walk()

  • 類能否呼叫實體方法:不能,比如Human.say()

    TypeError: say() missing 1 required positional argument: 'self'
    

小結

方法 裝飾器 引數 呼叫方
類方法 @classmethod cls 類,範例(不推薦)
實體方法 self 範例
靜態方法 @staticmethod 無預設引數 類(推薦),範例(不推薦)

cls代指類本身,self代指範例

class Person:
    @classmethod
    def eat(cls): # 這裡的cls就是指Person
        pass
    def drink(self): # 這裡的self就是指Person()出來的範例
        pass

cls和self這2個名字只是約定,見名知義,不建議更改,IDE會給你提示,其他地方需要自己注意,事實上你可以寫成任意的名字,但不推薦

class Person:
    @classmethod
    def eat(class_name): 
        print('eat')
    def drink(instance_name):
        print('drink')
Person.eat()   # 沒毛病
Person().drink()  # 沒毛病

pycharm中的提示資訊

官網

@classmethod

把一個方法封裝成類方法。

一個類方法把類自己作為第一個實參,就像一個實體方法把範例自己作為第一個實參。請用以下習慣來宣告類方法:

class C:
    @classmethod
    def f(cls, arg1, arg2): ...

@classmethod 這樣的形式稱為函數的 decorator

類方法的呼叫可以在類上進行 (例如 C.f()) 也可以在範例上進行 (例如 C().f())。 其所屬類以外的類範例會被忽略。 如果類方法在其所屬類的派生類上呼叫,則該派生類物件會被作為隱含的第一個引數被傳入。

類方法與 C++ 或 Java 中的靜態方法不同。 如果你需要後者,請參閱本節中的 staticmethod()

@staticmethod

將方法轉換為靜態方法。

靜態方法不會接收隱式的第一個引數。要宣告一個靜態方法,請使用此語法

class C:
    @staticmethod
    def f(arg1, arg2, ...): ...

@staticmethod 這樣的形式稱為函數的 decorator

靜態方法的呼叫可以在類上進行 (例如 C.f()) 也可以在範例上進行 (例如 C().f())。

Python中的靜態方法與Java或C ++中的靜態方法類似。另請參閱 classmethod() ,用於建立備用類建構函式的變體。

像所有裝飾器一樣,也可以像常規函數一樣呼叫 staticmethod ,並對其結果執行某些操作。比如某些情況下需要從類主體參照函數並且您希望避免自動轉換為實體方法。對於這些情況,請使用此語法:

class C:
    builtin_open = staticmethod(open)