class __init __(不是实例__init__)

时间:2010-04-24 22:32:30

标签: python class initialization self-reference

这是我想要解决的一个非常简单的例子:

class Test(object):
    some_dict = {Test: True}

问题在于,当它仍然被定义时,我无法引用测试

通常情况下,我会这样做:

class Test(object):
    some_dict = {}
    def __init__(self):
        if self.__class__.some_dict == {}:
            self.__class__.some_dict = {Test: True}

但我从来没有创建过这个类的实例。它实际上只是一个容纳一组相关函数和数据的容器(我有几个这样的类,我传递对它们的引用,所以必须使Test成为它自己的类)< / p>

所以我的问题是,在定义时,我怎么能引用Test,或者在定义类之后是否有与__init__类似的东西?如果可能,我希望self.some_dict = {Test: True}保留在类定义中。到目前为止,这是我知道如何做到这一点的唯一方法:

class Test(object):
    @classmethod
    def class_init(cls):
        cls.some_dict = {Test: True}
Test.class_init()

5 个答案:

答案 0 :(得分:12)

在定义时,该类确实不存在。 class语句的工作方式是语句的主体作为代码块在单独的命名空间中执行。在执行结束时,该命名空间将传递给元类(例如type),并且元类使用命名空间作为属性空间创建类。

根据您的描述,测试成为一个类需要 not 声音。听起来它应该是模块some_dict是一个全局 - 即使它是一个类属性,程序中只有一个这样的属性,所以它没有比拥有全局更好 - 并且你在类中拥有的任何类方法都可以只是函数。

如果你真的希望它成为一个类,你有三个选择:在定义类之后设置dict:

class Test:
    some_dict = {}
Test.some_dict[Test] = True

使用类装饰器(在Python 2.6或更高版本中):

def set_some_dict(cls):
    cls.some_dict[cls] = True

@set_some_dict
class Test:
    some_dict = {}

或者使用元类:

class SomeDictSetterType(type):
    def __init__(self, name, bases, attrs):
        self.some_dict[self] = True
        super(SomeDictSetterType, self).__init__(name, bases, attrs)

class Test(object):
    __metaclass__ = SomeDictSetterType
    some_dict = {}

答案 1 :(得分:4)

您可以在主类定义之后添加some_dict属性。

class Test(object):
  pass
Test.some_dict = {Test: True}

答案 2 :(得分:1)

我过去曾尝试以这种方式使用类,并且它很快变得丑陋(例如,所有方法都需要是类方法或静态方法,你最终可能会想到你想要的定义某些特殊方法,您必须开始使用元类)。如果您只使用类实例,它可以使事情变得更容易 - 实际上没有任何缺点。

替代其他人建议的(看起来很奇怪)替代方案:您可以使用__new__

class Test(object):
    def __new__(cls):
        cls.some_dict = {cls: True}

Test()

你甚至可以让__new__返回对类的引用并使用装饰器来调用它:

def instantiate(cls):
    return cls()

@instantiate
class Test(object):
    def __new__(cls):
        cls.some_dict = {cls: True}
        return cls

答案 3 :(得分:0)

你也可以使用元类(这里有一个函数,但还有其他方法):

def Meta(name, bases, ns):
    klass = type(name, bases, ns)
    setattr(klass, 'some_dict', { klass: True })
    return klass

class Test(object):
    __metaclass__ = Meta

print Test.some_dict

答案 4 :(得分:0)

托马斯的第一个例子非常好,但这是一种更多的Pythonic方式做同样的事情。

class Test:
    x = {}
    @classmethod
    def init(cls):
        # do whatever setup you need here
        cls.x[cls] = True
Test.init()