Python 类实例作为静态属性
Python 3不允许在类的主体内引用类(方法中除外): 这会在第二行中引发Python 类实例作为静态属性,python,class,python-3.x,static-methods,language-design,Python,Class,Python 3.x,Static Methods,Language Design,Python 3不允许在类的主体内引用类(方法中除外): 这会在第二行中引发名称错误,因为未定义“a” 选择 我很快找到了一个解决办法: class A: @property @classmethod def static_property(cls): return A() def __init__(self): ... 尽管这并不完全相同,因为它每次都返回不同的实例(您可以通过第一次将实例保存到静态变量来防止这种情况) 是否有
名称错误
,因为未定义“a”
选择
我很快找到了一个解决办法:
class A:
@property
@classmethod
def static_property(cls):
return A()
def __init__(self):
...
尽管这并不完全相同,因为它每次都返回不同的实例(您可以通过第一次将实例保存到静态变量来防止这种情况)
是否有更简单和/或更优雅的选择
编辑:
我已将有关此限制原因的问题移动到a表达式a()
在定义类a
之前无法运行。在您的第一个代码块中,A
的定义在您尝试执行A()
时不完整
这里有一个更简单的选择:
class A:
def __init__(self):
...
A.static_attribute = A()
您可以使用类装饰器:
def set_static_attribute(cls):
cls.static_attribute = cls()
return cls
@set_static_attribute
class A:
pass
现在:
>>A.static\u属性
在类的顶部应用decorator比在潜在的长类定义之后设置
static\u属性
更显式。应用的装饰器“属于”类定义。因此,如果在源代码中移动该类,则更可能将其移动,而不是在该类外部额外设置属性 使用属性
装饰器是一种可行的方法,但需要这样做:
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>
A类:
_静态属性=无
@财产
def静态_属性(自身):
如果.._static_属性为无:
A.。_static_属性=A()
返回一个.._static_属性
定义初始化(自):
通过
a=a()
打印(a.static_属性)#->
b=A()
打印(b.static_属性)#->
定义类时,Python会立即执行定义中的代码。请注意,这与定义Python编译代码但不执行代码的函数不同
这就是为什么这会产生错误:
class MyClass(object):
a = 1 / 0
但这不会:
def my_func():
a = 1 / 0
在A
的类定义主体中,A
尚未定义,因此在定义之后才能引用它
有几种方法可以实现您的要求,但我不清楚为什么这在第一时间会有用,因此如果您能提供有关用例的更多详细信息,就可以更容易地建议采用哪种方法
最简单的方法是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()
如果您提供了一个案例,让一个类的实例成为同一个类的属性是有用的,那么这将是一个更有趣的问题。例如,与Java不同,您可以拥有存在于类定义之外的对象。
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()