这是我想要解决的一个非常简单的例子:
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()
答案 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()