2013-08-21 56 views
2

我注意到python不會讓你添加一個類的實例作爲類定義的靜態成員。自己類型的python靜態字段

>>> class Foo: 
...  A = Foo() 
... 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 2, in Foo 
NameError: name 'Foo' is not defined 

但以下兩種工作:

>>> class Foo: 
...  pass 
... 
>>> class Foo: 
...  A = Foo() 
... 
>>> Foo.A 
<__main__.Foo instance at 0x100854440> 

>>> class Foo: 
...  pass 
... 
>>> Foo.A = Foo() 
>>> 
>>> Foo.A 
<__main__.Foo instance at 0x105843440> 

我無法找到任何啓​​發的代碼示例或解釋。爲什麼python以不同的方式處理第一個案例? A在以後兩個案例中的每一個案例中都有哪些?

回答

6

您的第一個示例不起作用,因爲您尚未創建類Foo。你正在這樣做(因此NameError

你的第二個例子工作,因爲你有一個叫Foo()類。你重寫它,但你仍然保留它的副本。看看這個:

>>> class Foo: 
...  def __init__(self): 
...    print 'hi' 
... 
>>> class Foo: 
...  A = Foo() 
... 
hi 
>>> Foo.A 
<__main__.Foo instance at 0x101019950> 
>>> Foo.A.__init__ 
<bound method Foo.__init__ of <__main__.Foo instance at 0x101019950>> 

A是一個屬性,它具有您所覆蓋的類的值。

至於你的第三個例子,你只是簡單地將一個類的屬性作爲這個類的一個實例。

3

編輯:看this question在Python中自引用類的例子。)

我認爲這將拼出來:

>>> class Test: 
...  a = 3 
... 
>>> class Test: 
...  m = Test() 
... 
>>> 
>>> t = Test() 
>>> t.m 
<__main__.Test object at 0x01E73690> 
>>> t.a 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
AttributeError: 'Test' object has no attribute 'a' 
>>> t.m.a 
3 

令人驚訝的是,這爲您提供了兩種不同類型的同名。但我想第一堂課是「迷失」的,只能通過第二堂。

1

創建一個類首先評估它的主體,然後創建一個類對象。

所以

class Foo: 
    A = Foo() # here class Foo doesn't exist yet 
# but here it exists. 

Here是如何創建一個類對象的作品。)

你的第二個示例創建一個類,然後使用相同的名稱,而不是與在第一個創建另一個類任何方式。因此,

>>> isinstance(Foo.A, Foo) 
False 

你的第三個例子在它的創建後使用它來擴展它。

所以,

>>> isinstance(Foo.A, Foo) 
True 

爲什麼蟒蛇不同的方式對待第一種情況?

因爲標識符還不存在。

在以後兩個案例中的每一個案例中,哪一個在哪裏?

這是什麼意思,它到底在哪裏?

0

在類定義時間,類本身還不存在,執行縮進塊的內容並解析任何名稱並調用函數。此時,類的名稱,基類和包含要存儲在類中的名稱和值的字典將傳遞給元類,該類創建實際的類並將其綁定到指定的名稱。您可以在類初始化時通過使用metaclass創建類的「靜態」實例。這將執行類定義中的代碼,將名稱,基礎和詞典傳遞給元類函數,該函數創建類並在其中創建類的實例,然後將其綁定到名稱。試想一下:

def staticInstanceMetaclass(name, bases, dict_): 
    ret=type(name, bases, dict_) 
    for i in dict_: 
     if dict_[i]=='STATICINSTANCE': 
     setattr(ret,i,ret()) 
    return ret 

class ClassWithStaticInstance(object): 
    __metaclass__=staticInstanceMetaclass 
    myStaticInstance='STATICINSTANCE' 
    myFirstVar=5 

print ClassWithStaticInstance.myStaticInstance 

注意,在上面的例子中,dict_包含

{'myStaticInstance': 'STATICINSTANCE', '__module__': '__main__', '__metaclass__': <function staticInstanceMetaclass at 0x1213668>, 'myFirstVar': 5} 

當你到預先在Python中創建靜態情況下,這是我們所密切。有關元類的更多信息,以及如何影響類的創建,請參閱this問題。

相關問題