您好,登錄后才能下訂單哦!
小編給大家分享一下python中staticmethod與classmethod的示例分析,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
python在類中,有三種調(diào)用method的方法:普通method,staticmethod和classmethod
前兩個(gè)應(yīng)該都好理解,classmethod就是在調(diào)用這個(gè)函數(shù)的時(shí)候,會(huì)把調(diào)用對(duì)象的class object對(duì)象隱式地傳進(jìn)去。咦?這個(gè)class object不是一個(gè)類型?No,在python里面,class object不像靜態(tài)語言一樣是個(gè)類型,它在虛擬機(jī)中,就是一個(gè)對(duì)象。普通method調(diào)用需要把自己self作為參數(shù)傳遞,初學(xué)的時(shí)候怎么著也不能理解,不過看多了就自然熟悉了。比較奇怪的是staticmethod和classmethod不像靜態(tài)語言一樣,通過保留關(guān)鍵字定義,而是使用@staticmethod
或者staticmethod()
這種builtin函數(shù)進(jìn)行定義。這個(gè)@staticmethod
到底是個(gè)什么東東?
@staticmethod def foo(x): print(x)
之前用過java,所以第一反應(yīng)這是個(gè)annotation……唔,確實(shí)感覺像個(gè)AOP的東西,python里把它稱作decorator。如果我們要自己實(shí)現(xiàn)一個(gè)staticmethod,該怎么寫呢?
研究了下官方的代碼,我再改了改,感覺應(yīng)該這樣寫:
def foo(x): print(x) class StaticMethod(object): def __init__(self, function): print("__init__() called") self.f = function def __get__(self, instance, owner): print("\t__get__() called") print("\tINFO: self = %s, instance =%s, owner = %s" % (self, instance, owner)) return self.f class Class1(object): method = StaticMethod(foo) if __name__ == '__main__': ins = Class1() print("ins = %s, Class1 = %s" % (ins, Class1)) print("ins.method = %s, Class1.method = %s" % (ins.method, Class1.method)) ins.method('abc') Class1.method('xyz')
輸出結(jié)果是:
__init__() called
ins = <__main__.Class1 object at 0xece2d0>, Class1 = <class '__main__.Class1'>
__get__() called
INFO: self = <__main__.StaticMethod object at 0xece5d0>, instance =<__main__.Class1 object at 0xece2d0>, owner = <class '__main__.Class1'>
__get__() called
INFO: self = <__main__.StaticMethod object at 0xece5d0>, instance =None, owner = <class '__main__.Class1'>
ins.method = <function foo at 0xeb6c00>, Class1.method = <function foo at 0xeb6c00>
__get__() called
INFO: self = <__main__.StaticMethod object at 0xece5d0>, instance =<__main__.Class1 object at 0xece2d0>, owner = <class '__main__.Class1'>
abc
__get__() called
INFO: self = <__main__.StaticMethod object at 0xece5d0>, instance =None, owner = <class '__main__.Class1'>
xyz
嗯,看上去一切都挺順利,Class1包含了一個(gè)變量method,不過這個(gè)method其實(shí)也是一個(gè)特殊處理過的StaticMethod類。這個(gè)類中有一個(gè)__get__
函數(shù),當(dāng)類被“get”的時(shí)候,被訪問的時(shí)候,會(huì)默認(rèn)把訪問者的instance和class信息都傳進(jìn)來。所以我們看到不管是否調(diào)用method()這個(gè)函數(shù),只要碰著了method,這個(gè)函數(shù)就會(huì)觸發(fā),就會(huì)打印出當(dāng)前instance和class信息。雖然ins和Class1的instance各有不同,但__get__
函數(shù)中只是返回foo函數(shù),所以這里調(diào)用method之時(shí)就沒有區(qū)別,調(diào)用的都是同一個(gè)function對(duì)象。
好的,那么classmethod又如何實(shí)現(xiàn)呢?
def foo2(cls, x): print("foo2's class = ", cls) print(x) class ClassMethod(object): def __init__(self, function): print("ClassMethod: __init__() called") self.f = function def __get__(self, instance, owner = None): print("\t__get__() called") print("\tINFO: self = %s, instance =%s, owner = %s" % (self, instance, owner)) def tmpfunc(x): print("I'm tmpfunc") return self.f(owner, x) return tmpfunc class Class2(object): method = ClassMethod(foo2) class Class21(Class2): pass if __name__ == '__main__': ins = Class2() print("ins.method = %s, Class2.method = %s, Class21.method = %s" % (ins.method, Class2.method, Class21.method)) ins.method('abc') Class2.method('xyz') Class21.method('asdf')
輸出結(jié)果是:
ClassMethod: __init__() called
__get__() called
INFO: self = <__main__.ClassMethod object at 0xdeb250>, instance =<__main__.Class2 object at 0xdeb350>, owner = <class '__main__.Class2'>
__get__() called
INFO: self = <__main__.ClassMethod object at 0xdeb250>, instance =None, owner = <class '__main__.Class2'>
__get__() called
INFO: self = <__main__.ClassMethod object at 0xdeb250>, instance =None, owner = <class '__main__.Class21'>
ins.method = <function tmpfunc at 0xdee050>, Class2.method = <function tmpfunc at 0xdee1e8>, Class21.method = <function tmpfunc at 0xdee270>
__get__() called
INFO: self = <__main__.ClassMethod object at 0xdeb250>, instance =<__main__.Class2 object at 0xdeb350>, owner = <class '__main__.Class2'>
I'm tmpfunc
foo2's class = <class '__main__.Class2'>
abc
__get__() called
INFO: self = <__main__.ClassMethod object at 0xdeb250>, instance =None, owner = <class '__main__.Class2'>
I'm tmpfunc
foo2's class = <class '__main__.Class2'>
xyz
__get__() called
INFO: self = <__main__.ClassMethod object at 0xdeb250>, instance =None, owner = <class '__main__.Class21'>
I'm tmpfunc
foo2's class = <class '__main__.Class21'>
asdf
可以看出,classmethod和staticmethod的實(shí)現(xiàn)方法是大同小異。staticmethod比較簡(jiǎn)單,直接返回self.f變量就好了,而classmethod不行,需要把調(diào)用時(shí)候的class類型信息傳給foo2函數(shù),這個(gè)函數(shù)根據(jù)接收的class信息來作不同的工作。(不過我現(xiàn)在也沒有想到可以用來做些什么)
有個(gè)地方值得注意,可能同志們剛才也已經(jīng)想到了,我一定必須要定義一個(gè)tempfunc,再返回它才能完成工作嗎?可不可以不要
def tmpfunc(x): print("I'm tmpfunc") return self.f(owner, x) return tmpfunc
而直接返回一個(gè)
return self.f(owner, *args)
我剛試了一把,直接傳args默認(rèn)參數(shù)是不行的,因?yàn)?code>__get__被調(diào)用的時(shí)候,還沒有把參數(shù)傳進(jìn)來。只有return tmpfunc之后,Class2.method('xyz')
的參數(shù)才掛在tmpfunc之上。
以上是“python中staticmethod與classmethod的示例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。