5

我正在尝试将一个变量添加到一个包含该类实例的类中。以下是我的代码的缩短版本。

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

4 回答 4

2

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

class Classy :
    CLASSIES = []

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

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

(为了方便起见,这里使用列表推导,因为它是构建列表的最易读和最有效的方式)。

另请注意,如果这打算成为一个常量,您可能应该将其设为元组而不是列表,如果不打算这样做,您可能不应该使用ALL_CAPS按照惯例暗示常量的名称。

于 2013-02-12T20:29:37.607 回答
2

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

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

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

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

于 2013-02-12T20:31:53.093 回答
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

而使用delnan'code的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

Delnan,你将如何继续假装 CLASSIES 是全球性的?
在您与 Lattyware 的辩论中,我是否误解了某些内容?

于 2013-02-12T21:00:05.590 回答
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>]
于 2013-02-12T20:29:44.753 回答