Python实例化类定义中的类

时间:2013-02-12 20:28:14

标签: python class constructor initialization static-variables

我试图将一个变量添加到一个保存类的实例的类中。以下是我的代码的缩短版本。

class Classy :
    def __init__(self) :
        self.hi = "HI!"
    # "CLASSIES" variable holds instances of class "Classy"
    CLASSIES = []
    for i in xrange(0,4) :
        CLASSIES.append(Classy())

运行代码后,我收到以下错误。

Traceback (most recent call last):
  File "classy.py", line 6, in Classy
    CLASSIES.append(Classy())
NameError: name 'Classy' is not defined

是否有另一种方法可以将类的实例添加到该类中的类/静态变量中?

4 个答案:

答案 0 :(得分:3)

在创建类之前执行类主体。因此,您尝试在类存在之前实例化该类。您仍然可以将实例附加到类,但您必须在类主体完成后创建它们,例如:

class Classy(object):
    def __init__(self):
        self.hi = "HI!"
    CLASSIES = []

for i in xrange(4):
    Classy.CLASSIES.append(Classy())

但是,我建议你首先想一想你是否真的需要这个有效的全局列表,以及你是否需要它成为类对象的一部分。就个人而言,我几乎从未做过这样的事情。

答案 1 :(得分:2)

最简单的方法是在创建类之后,定义类时执行此操作,因此可以使用:

class Classy :
    CLASSIES = []

    def __init__(self) :
        self.hi = "HI!"

Classy.CLASSIES = [Classy() for _ in xrange(0,4)]

(这里使用list comprehension方便,因为这是构建列表最可读和最有效的方法。)

另请注意,如果这是一个常量,你应该把它变成一个元组而不是一个列表,如果它不是,你可能不应该使用ALL_CAPS这个名字,按惯例,暗示一个常数。

答案 2 :(得分:2)

在我看来,你想要获得:

class Classy :
    CLASSIES = []
    def __init__(self) :
        self.hi = "HI!"
        Classy.CLASSIES.append(self)

for i in xrange(4):
    Classy()

for x in  Classy.CLASSIES:
    print x

结果

<__main__.Classy instance at 0x011DF3F0>
<__main__.Classy instance at 0x011DF440>
<__main__.Classy instance at 0x011DF418>
<__main__.Classy instance at 0x011DF2B0>

修改

请注意使用Lattyware的代码:

class Classy :
    CLASSIES = []
    idC = id(CLASSIES)
    def __init__(self) :
        self.hi = "HI!"
        #Classy.CLASSIES.append(self)


Classy.CLASSIES = [Classy() for _ in xrange(0,4)]

print Classy.idC
print id(Classy.CLASSIES)
print 'Classy.idC==id(Classy.CLASSIES) :',Classy.idC==id(Classy.CLASSIES)

结果

18713576
10755928
Classy.idC==id(Classy.CLASSIES) : False

使用denan'代码的for循环时,它不会出现。

但是很容易纠正:
写作
Classy.CLASSIES[:] = [Classy() for _ in xrange(0,4)]

Classy.CLASSIES.extend(Classy() for _ in xrange(0,4))
而不是 Classy.CLASSIES = [Classy() for _ in xrange(0,4)]
这取决于你想要什么。

编辑2

  

方法可以像普通方式一样引用全局名称   功能。与方法关联的全局范围是模块   包含其定义。 (一个类永远不会被用作全局范围。)

     

http://docs.python.org/2/tutorial/classes.html#class-definition-syntax

     

类具有由字典对象实现的命名空间。类   属性引用被转换为此字典中的查找,   例如,C.x被翻译为C.__dict__["x"]

     

http://docs.python.org/2/reference/datamodel.html#new-style-and-classic-classes

class Classy :
    CLASSIES = []

print '"CLASSIES" in globals()',"CLASSIES" in globals()
print '"CLASSIES" in Classy.__dict__ ==',"CLASSIES" in Classy.__dict__

结果

"CLASSIES" in globals() False
"CLASSIES" in Classy.__dict__ == True
德尔南,你将如何继续假装CLASSIES是全球性的? 我在与Lattyware的辩论中误解了什么吗?

答案 3 :(得分:1)

在类块完成执行之后才会定义类本身,因此您无法在其自己的定义中使用该类。

在创建类之后,您可以使用类装饰器或元类来添加所需的类变量。这是一个装饰器的例子。

def addClassy(cls):
    cls.CLASSIES = [cls() for a in xrange(4)]
    return cls

@addClassy
class Classy(object):
    pass

>>> Classy.CLASSIES
0: [<__main__.Classy object at 0x000000000289A240>,
 <__main__.Classy object at 0x000000000289A518>,
 <__main__.Classy object at 0x000000000289A198>,
 <__main__.Classy object at 0x000000000289A208>]