类的 __init__ (不是实例的 __init__)
这里有一个我想解决的非常简单的例子:
class Test(object):
some_dict = {Test: True}
问题是,在定义 Test 的时候,我无法引用它。
通常,我会这样做:
class Test(object):
some_dict = {}
def __init__(self):
if self.__class__.some_dict == {}:
self.__class__.some_dict = {Test: True}
但是我从来没有创建这个类的实例。这个类其实只是用来装一组相关的函数和数据(我有好几个这样的类,我会传递它们的引用,所以 Test 必须是一个独立的类)。
所以我的问题是,在定义 Test 的时候,我该如何引用它,或者有没有类似于 __init__
的东西,可以在类定义完成后立即调用?如果可以的话,我希望 self.some_dict = {Test: True}
能留在类的定义里面。这是我目前知道的唯一方法:
class Test(object):
@classmethod
def class_init(cls):
cls.some_dict = {Test: True}
Test.class_init()
5 个回答
我之前也尝试过这样使用类,结果很快就变得复杂了(比如,所有的方法都得是类方法或者静态方法,最后你可能会发现想定义一些特殊的方法,这时候就得开始用元类了)。如果你直接使用类的实例,事情会简单很多,基本上没有什么坏处。
还有一种(看起来有点奇怪的)替代方案:你可以使用 __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
你可以在主类定义之后添加一些字典属性。
class Test(object):
pass
Test.some_dict = {Test: True}
其实在定义一个类的时候,这个类并不存在。class
这个语句的工作方式是,它的内容会作为一段代码在一个独立的命名空间中执行。执行结束后,这个命名空间会被传递给元类(比如type
),然后元类会用这个命名空间来创建类,命名空间里的内容就成了类的属性。
根据你的描述,Test似乎并不一定要是一个类。听起来它更像是一个模块。some_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 = {}