不幸的是,在Python中,类属性无法引用其类名。以下引发了一个名称错误:
class Foo(object):
bar = Foo
在class属性必须引用其类名(在我的情况下,它是库的验证方案的一部分)的情况下,最明智的方法是什么?
以下是我目前的尝试:
class Foo(object):
bar = None
Foo.bar = Foo
这样可行,但即使有注释也可能会引起混淆,因为您希望在声明时初始化类属性,而不是在声明类之后。
有没有人有更好的解决方法?
答案 0 :(得分:2)
您可以使用类装饰器
def moi(fieldname):
def _selfref(cls):
setattr(cls, fieldname, cls.__name__)
return cls
return _selfref
用法:
@moi('bar')
class Foo(object):
pass
然后:
>>> print Foo.bar
Foo
答案 1 :(得分:2)
您可以定义一个类装饰器,用所定义的类替换占位符字符串:
def fixup(cls):
placeholder = '@' + cls.__name__
for k,v in vars(cls).items():
if v == placeholder:
setattr(cls, k, cls)
return cls
@fixup
class Foo(object):
bar = '@Foo'
print('Foo.bar: {!r}'.format(Foo.bar)) # -> Foo.bar: <class '__main__.Foo'>
答案 2 :(得分:2)
使用元类自动设置它。
def my_meta(name, bases, attrs):
cls = type(name, bases, attrs)
cls.bar = cls
return cls
class Foo(object):
__metaclass__ = my_meta
>>> print Foo.bar
<class '__main__.Foo'>
答案 3 :(得分:1)
你可以use metaclasses。定义一个__new__
迭代set属性,然后设置返回指向类本身的指针。
答案 4 :(得分:0)
如果您只想要''别名''__class__
?
@property
def bar(self):
return self.__class__
如果你玩一些继承,它就会产生问题。
答案 5 :(得分:0)
您可以使用lambda表达式:
class Foo(object):
bar = lambda: Foo
这违反了PEP 8,但有效