在类定义中实例化类

6 投票
4 回答
10603 浏览
提问于 2025-04-17 15:40

我正在尝试给一个类添加一个变量,这个变量用来保存这个类的实例。下面是我代码的简化版本。

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 个回答

2

最简单的方法是在类创建之后,也就是类定义好之后再进行操作,这样就可以使用这个类了:

class Classy :
    CLASSIES = []

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

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

(这里使用了列表推导式,因为它是构建列表最清晰和高效的方法)。

另外,如果你打算把这个当作常量使用,最好把它做成一个元组,而不是列表。如果不是常量,建议不要用ALL_CAPS这种命名方式,因为按照惯例,这种命名方式通常表示常量。

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的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的讨论中理解错了什么?

2

类的主体在类被创建之前就会执行。因此,你是在类还不存在的时候就试图去实例化它。虽然你可以把实例附加到类上,但你必须在类的主体执行完之后再去创建它们,比如:

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

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

不过,我建议你先认真考虑一下,自己是否真的需要这个几乎是全局的列表,以及是否需要把它作为类的一部分。就我个人而言,我几乎从来不这样做。

撰写回答