在class属性中引用类名的最佳方法是什么?

时间:2015-12-06 17:27:40

标签: python

不幸的是,在Python中,类属性无法引用其类名。以下引发了一个名称错误:

class Foo(object):
    bar = Foo

在class属性必须引用其类名(在我的情况下,它是库的验证方案的一部分)的情况下,最明智的方法是什么?

以下是我目前的尝试:

class Foo(object):
    bar = None
Foo.bar = Foo

这样可行,但即使有注释也可能会引起混淆,因为您希望在声明时初始化类属性,而不是在声明类之后。

有没有人有更好的解决方法?

6 个答案:

答案 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,但有效