python中的builtin函數詳解-第二篇


classmethod(function)
這里不過多說明這個builtin方法的具體用法,python的文檔和help函數已經給了這個方法充足的使用說明,所以我這里要說的時關於 classmethod , property之流的注解方法背后所用的技術細節,也是python中比較難以理解的一個知識點, 那就是 python中的 描述符。
從現象開始分析
class Person(object):
	country = 'china'
	def __init__(self, name):
		self.name = name
	def say(self):
		print self.name

這個類開始分析,首先運行如下代碼

me = Person('younger')
Person.__dict__
me.__dict__

結果為

>>> Person.__dict__
dict_proxy({'__module__': '__main__', 'country': 'china', 'age': 20, 'say': 	<function say at 0x1047e0b18>, '__dict__': <attribute '__dict__' of 'Person' 	objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>, '	__doc__': None, '__init__': <function __init__ at 0x1047e0b90>})

>>> me.__dict__
{'name': 'younger'}

我們的類和實例都具有__dict__屬性,這個字典中囊括了該對象中所有的屬性(類也是對象)。

繼續運行代碼

me.country

結果為

>>> me.country
'china'

繼續運行代碼

me.__dict__['country]

結果為

>>> me.__dict__['country']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'country'

由此可見,當我們調用實例屬性的時候,me.name和me.dict['name'] 的結果是一樣的,當調用的是類屬性的時候,就截然不同了,結果顯而易見,當我們再調用不同的屬性的時候,系統會自動做出一些判斷,但是我們現在還不知道判斷是怎么進行的,也不知道是什么時候進行的,這里還不做解答,再看一個關於類中方法調用的例子。

我們繼續運行代碼

Person.say
Person.__dict__['say']

me.say
me.__dict__['say']

運行結果為

>>> Person.say
<unbound method Person.say>
>>> Person.__dict__['say']
<function say at 0x1047e0b18>

>>> p.say
<bound method Person.say of <__main__.Person object at 	0x10473a190>>
>>> p.__dict__['say']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'say'

先不管方法有沒有被綁定,先看下結果,我們再用點和__dict__訪問一個方法的時候,得到的是全然不同的結果,理論上來說應該是會得到一樣的結果,因為都是要再當前對象的__dict__ 中進行查找,為什么Person的返回會完全不同呢?而且就返回結果來說,Person.say返回的結果類型為 未綁定的instancemethod, 而 Person.__dict__['say'] 返回的是普通的function類型對象, 方法的返回和調用完全和與其的不一樣, 這就是描述符的作用。

官方對描述符的定義是:

一個描述符, 是一個對象對某個 “綁定” 方法的描述。

用自己的話來說,就是一個類中實現一些類似於 __get__, __set__, __getattr__, __getattribute__ 的方法,然后再對屬性進行各種操作的時候,這些方法將會進行類似過濾的操作,來幫助你做一些額外的工作。

拿上面的例子來說,調用一個方法有兩種情況,一種是在類中調用,另一種是實例種調用,如果是對象種調用,那么對象的 __getattribute__方法會做返回 type(obj).__dict__['func'].__get__(obj, type(obj)), 如果是類在調用,那么會被返回為 cls.__dict__['func'].__get__(None, cls), 這里___getattribute__, 起到了巨大的作用,用各種get方法進行了過濾, 所以在對方法進行操作的時候,用點和__dict__進行調回會有不同的結果,這也是描述符的作用所在。

你可以寫自己的描述符,來對屬性的讀寫進行操作。

現在我們回到staticmethod這個裝飾器方法上來

class StaticMethod(object):
	"Emulate PyStaticMethod_Type() in Objects/funcobject.c
	def __init__(self, f):
  			self.f = f
  		def __get__(self, obj, objtype=None):
  			return self.f

上面是文檔種對這個方法的python模擬,實際上builtin種的方法都是c的方法,該裝飾器在get的時候進行自定義操作。

舉個例子

>>> class E(object):
 			def f(klass, x):
      			return klass.__name__, x
 			f = classmethod(f)
>>> print E.f(3)
	('E', 3)
>>> print E().f(3)
	('E', 3)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM