2013-07-03 2 views
0

Я создаю несколько экземпляров моего класса в цикле и ожидаю, что они будут независимыми. Но к моему смущению, когда я создаю новый экземпляр с тем же именем, он сохраняет свойства экземпляра, созданного ранее.путаница о экземплярах классов

Так что у меня что-то вроде:

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 

Так для 1-й раз это петли, pprint показывает o.property1 = [] во второй раз, он показывает o.property1 список все, что есть добавляется к o в первом запуске цикла.

Мое понимание было то, что, когда я звоню о = MyClass(), новый экземпляр этого класса будет создан, и старый будет удален (эффективно overwrtitten)

Может кто-нибудь объяснить мне, как питон здесь работает и как я могу заставить его работать так, как я хочу?

Если изменить класс

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 в качестве входных переменных и все еще иметь желаемое поведение?

+7

Этот код на самом деле не работает, и трудно понять, что делает ваш реальный код. Попробуйте создать [SSCCE] (http://sscce.org), который демонстрирует вопрос. – abarnert

+4

Я предполагаю, что, хотя код, который вы пишете, не отражает этого, вы на самом деле используете переменные класса (а не 'self.property1 = []', которые вы показываете здесь). Они действительно разделяются между экземплярами класса. Но вам нужно сделать фактически воспроизводимый пример вашей проблемы, чтобы мы имели представление о том, что это такое –

+0

Каждый раз, когда вы создаете экземпляр класса ('myClass()'), он создает новый объект, поэтому он не будет «перезаписывать» любой другие экземпляры этого класса. – astephenb

ответ

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 обычно уничтожают его либо на следующем проходе коллектора, но некоторые из них могут просто перемещать или маркировать его и уничтожать на следующем проходе.

Смежные вопросы