关于类实例的混淆

时间:2013-07-03 19:36:33

标签: python class

我在循环中创建了我的类的几个实例,并期望它们是独立的。但令我困惑的是,当我创建一个具有相同名称的新实例时,它会保留之前创建的实例的属性。

所以我有类似的东西:

class myClass(object):
    def __init__(self, i1 = None, i2 = 'X', p1 = [], p2 = []):
        self.i1, self.i2 = i1,i2
        self.property1 = p1
        self.property2 = p2

    def doStuff(self):        
        self.property1.append(self.i1)
        self.property2.append(self.i2)
        print self.property1
        print self.property2

class mySubClass(myClass):
    def __init__(self, i1 = None, i2 = 'Z'):
        myClass.__init__(self, i1, i2)



inputTuples = (('A', 'B'), ('D', 'E'))

for x,y in inputTuples:
    o=mySubClass(x)
    pprint(vars(o))
    o.doStuff()
    print(id(o))


{'i1': 'A', 'i2': 'Z', 'property1': [], 'property2': []}
['A']
['Z']
37087832
{'i1': 'D', 'i2': 'Z', 'property1': ['A'], 'property2': ['Z']}
['A', 'D']
['Z', 'Z']
37088392

所以第一次循环,pprint显示o.property1 = [] 第二次,它显示o.property1是在循环的第一次运行中附加到o的任何内容的列表。

我的理解是,当我调用o = myClass()时,将创建该类的新实例,并删除旧实例(有效地覆盖)

有人可以向我解释一下python在这里是如何工作的,以及我如何让它按照我想要的方式工作?

如果我将课程改为

class myClass(object):
    def __init__(self, i1 = None, i2 = 'X':
        self.i1, self.i2 = i1,i2
        self.property1 = []
        self.property2 = []

一切正常

{'i1': 'A', 'i2': 'Z', 'property1': [], 'property2': []}
['A']
['Z']
37087832
{'i1': 'D', 'i2': 'Z', 'property1': [], 'property2': []}
['D']
['Z']
37088392

我不明白这里的根本区别。另外,如何保持将p1和p2作为输入变量的可能性仍然是理想的行为?

1 个答案:

答案 0 :(得分:3)

我已将您的代码修改为实际可运行,并且每次循环时都显示o对象的标识。最好去除所有明显无关的东西,但也许这会让你更容易理解。

from pprint import pprint

def f(x, y):
    return x+y

class myClass(object):
    def __init__(self, i1,i2,i3):
        self.i1, self.i2, self.i3 = i1,i2,i3
        self.property1 =[]

    def doStuff(self):
        someValue = f(self.i1,self.i2)
        self.property1.append(someValue)

inputTuples = ((1, 2, 3), (4, 5, 6))

for x,y,z in inputTuples:
    o=myClass(i1=x,i2=y,i3=z)
    pprint(vars(o))
    o.doStuff()
    print(id(o))

当你运行它时,你会看到类似这样的输出:

{'i1': 1, 'i2': 2, 'i3': 3, 'property1': []}
4302258000
{'i1': 4, 'i2': 5, 'i3': 6, 'property1': []}
4302258064

换句话说,每个连续的o实例具有不同的属性,并且也是不同的对象。 Python每次循环都会创建一个新的o

它可能会或可能不会立即破坏旧实例,但你不关心它;它会“最终”摧毁它,并做得很好,所以你可以忘掉它。


*使用此特定代码,CPython将立即销毁旧实例; PyPy,Jython和IronPython通常会在下一次收集器传递中销毁它,但是其中一些可能只是移动或标记它并在下一次传递中将其销毁。