我注意到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在哪里?
答案 0 :(得分: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
是一个属性,它具有您覆盖的类的值。
至于你的第三个例子,你只是创建一个类的属性,它是一个类的实例。
答案 1 :(得分: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
令人惊讶的是,它为您提供了两个具有相同名称的不同类。但我猜第一堂课“丢失了”,只能通过第二堂课获得。
答案 2 :(得分:1)
创建一个类的工作原理是首先评估它的主体,然后最后创建一个类对象。
所以
class Foo:
A = Foo() # here class Foo doesn't exist yet
# but here it exists.
(Here是创建类对象的方式。)
您的第二个示例创建一个类,然后创建另一个具有相同名称的类,与任何方式都不相关。因此,
>>> isinstance(Foo.A, Foo)
False
您的第3个示例在创建后使用该类来扩展它。
所以,
>>> isinstance(Foo.A, Foo)
True
为什么python以不同的方式处理第一种情况?
因为标识符尚不存在。
在后两个案例中,每个案件的A在哪里?
这是什么意思,它在哪里?
答案 3 :(得分:0)
在类定义时,类本身尚不存在,执行缩进块的内容并解析任何名称并调用函数。此时,类的名称,基类和包含要存储在类中的名称和值的字典将传递给元类,元类创建实际的类并将其绑定到指定的名称。您可以通过使用metaclass
在类初始化时创建类的“静态”实例。这将执行类定义中的代码,将name,bases和dict传递给元类函数,该函数创建类并在其中创建类的实例,然后将其绑定到名称。考虑:
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问题。