Python 3不允许您在其体内引用类(方法除外):
class A:
static_attribute = A()
def __init__(self):
...
这会在第二行中引发NameError
,因为'A' is not defined
。
我很快找到了一个解决方法:
class A:
@property
@classmethod
def static_property(cls):
return A()
def __init__(self):
...
虽然这不完全相同,因为它每次都返回一个不同的实例(你可以通过第一次将实例保存到静态变量来防止这种情况)。
是否有更简单和/或更优雅的替代品?
修改 的 我已将有关此限制原因的问题移至separate question
答案 0 :(得分:4)
在定义类A()
之前,无法运行表达式A
。在您的第一个代码块中,A
的定义在您尝试执行A()
时尚未完成。
这是一个更简单的选择:
class A:
def __init__(self):
...
A.static_attribute = A()
答案 1 :(得分:2)
定义类时,Python会立即执行定义中的代码。请注意,与定义Python编译代码的函数不同,但不执行它。
这就是造成错误的原因:
class MyClass(object):
a = 1 / 0
但是这不是:
def my_func():
a = 1 / 0
在A
的课程定义正文中,A
尚未定义,因此您无法在其定义之后引用它。< / p>
有几种方法可以完成您所要求的内容,但我不清楚为什么这样做会有用,所以如果您能提供有关您的用例的更多详细信息,它会更容易推荐哪条路走下去。
最简单的是khelwood
张贴的内容:
class A(object):
pass
A.static_attribute = A()
因为这是修改类创建,所以使用元类可能是合适的:
class MetaA(type):
def __new__(mcs, name, bases, attrs):
cls = super(MetaA, mcs).__new__(mcs, name, bases, attrs)
cls.static_attribute = cls()
return cls
class A(object):
__metaclass__ = MetaA
或者您可以使用描述符来延迟创建实例,或者如果您想进一步自定义对它的访问:
class MyDescriptor(object):
def __get__(self, instance, owner):
owner.static_attribute = owner()
return owner.static_attribute
class A(object):
static_attribute = MyDescriptor()
答案 2 :(得分:1)
使用property
装饰器是一种可行的方法,但需要这样做:
class A:
_static_attribute = None
@property
def static_attribute(self):
if A._static_attribute is None:
A._static_attribute = A()
return A._static_attribute
def __init__(self):
pass
a = A()
print(a.static_attribute) # -> <__main__.A object at 0x004859D0>
b = A()
print(b.static_attribute) # -> <__main__.A object at 0x004859D0>
答案 3 :(得分:0)
您可以使用类装饰器:
def set_static_attribute(cls):
cls.static_attribute = cls()
return cls
@set_static_attribute
class A:
pass
现在:
>>>> A.static_attribute
<__main__.A at 0x10713a0f0>
在类的顶部应用装饰器使其比在可能的长类定义之后设置static_attribute
更明确。应用的装饰者&#34;属于&#34;到类定义。因此,如果您在源代码中移动类,则更有可能移动它而不是类外的属性的额外设置。