[基於python 3.4編寫的答案;元類的語法在2中有所不同,但我認爲該技術仍然有效]
您可以使用元類...主要做到這一點。 Dappawit幾乎工程,但我認爲它也有缺陷:
class MetaFoo(type):
@property
def thingy(cls):
return cls._thingy
class Foo(object, metaclass=MetaFoo):
_thingy = 23
這讓你一個classproperty上富,但有一個問題...
print("Foo.thingy is {}".format(Foo.thingy))
# Foo.thingy is 23
# Yay, the classmethod-property is working as intended!
foo = Foo()
if hasattr(foo, "thingy"):
print("Foo().thingy is {}".format(foo.thingy))
else:
print("Foo instance has no attribute 'thingy'")
# Foo instance has no attribute 'thingy'
# Wha....?
這到底是怎麼回事?爲什麼我無法通過實例訪問類屬性?
在找到我相信的答案之前,我在這上面打了很久。 Python的@properties是描述符的一個子集,並從descriptor documentation(重點煤礦):屬性的訪問
默認行爲是獲取,設置或刪除對象的字典中 屬性。例如,a.x
具有查找鏈 開始a.__dict__['x']
,然後type(a).__dict__['x']
,並繼續通過 type(a)
不含元類的基類。
所以方法解析順序不包括我們的類屬性(或其他在元類中定義的)。它是可能使內置屬性裝飾器的行爲有所不同,但(引文需要)我得到了印象谷歌搜索開發人員有一個很好的理由(我不明白)做到這一點辦法。
這並不意味着我們運氣不好;我們可以在類本身就好訪問屬性...我們可以從type(self)
實例,我們可以用它來使@property調度中獲取類:
class Foo(object, metaclass=MetaFoo):
_thingy = 23
@property
def thingy(self):
return type(self).thingy
現在Foo().thingy
作品用於兩個班級和實例!如果一個派生類替代了它的基礎_thingy
(這是最初讓我參與這個狩獵的用例),它也將繼續做正確的事情。
這對我來說並不是100%滿意 - 必須在元類和對象類中進行設置纔會感覺違反了DRY原則。但後者只是一個單線調度員;我現在大部分都沒問題,如果你真的想要的話,你可以把它壓縮到一個lambda或什麼東西。
我不知道python ...這是你正在尋找的東西嗎? http://www.python.org/download/releases/2。2/descrintro /#屬性 – 2011-03-04 04:40:48
如果我正在閱讀這個權利,你可以創建方法來充當setter和getter(和其他語言一樣),這樣你就可以在第一次獲取屬性值時進行懶加載...我認爲你想要什麼? – 2011-03-04 04:45:56
@白龍。您正在查看的屬性功能將類屬性添加到類實例中,而不是類本身。我在問'Example.I'不是'e.i'。 – 2011-03-04 04:57:04