2013-12-04 4 views
0

Я пытаюсь создать новые объекты и сохранить их в словаре. Но, похоже, это не работает так, как я ожидаю.Явное создание нового объекта в Python

class Fruit: 
    name = '' 
    facts = [] 
    def __init__(self, FruitName): 
     self.name = FruitName 
     facts = [] 
    def addfact(self, FruitName): 
     if FruitName == 'banana': 
      self.facts.append('bananas contain potassium') 
     elif FruitName == 'orange': 
      self.facts.append('These are some facts about oranges') 
     else: 
      self.facts.append('Unrecognized fruit submitted') 

Files = ['banana', 'orange', 'apple'] 

ObjLibrary = {} 

for File in Files: 
    if not File in ObjLibrary: 
     ObjLibrary[File] = Fruit(File) 
    ObjLibrary[File].addfact(File) 

print ObjLibrary['banana'].facts 
print ObjLibrary['orange'].facts 
print ObjLibrary['apple'].facts 

я получаю следующий результат:

['bananas contain potassium', 'These are some facts about oranges', 'Unrecognized fruit submitted'] 
['bananas contain potassium', 'These are some facts about oranges', 'Unrecognized fruit submitted'] 
['bananas contain potassium', 'These are some facts about oranges', 'Unrecognized fruit submitted'] 

Теперь я подозреваю, что происходит в том, что я явно не создавая три объекта так, как я хочу, а просто указывает все три элемента в словаре к одному и тому же объекту. Мой вопрос: почему? На каждом проходе цикла File должно иметь другое значение. Что еще более важно, как мне обойти это? В моем «реальном» коде нецелесообразно создавать абсолютно новую переменную для хранения каждого объекта.

Благодарим за помощь.

Кейси

ответ

3

Проблема заключается в том, что facts является переменной класса, а не экземпляр один. Вы должны определить его в __init__ (и удалить ненужные локальные переменные декларации есть):

class Fruit: 

    def __init__(self, FruitName): 
     self.name = FruitName 
     self.facts = [] 

    def addfact(self, FruitName): 
     ... 

Примечание Python не Java, нет никакой необходимости «объявить» атрибуты на уровне класса.

+0

Не только не нужно, но если вы попытаетесь, то, что вы действительно делаете, объявляет атрибуты static/class. Обратите внимание, что вы можете сделать '__slots__ = ['name', 'Facts']', чтобы объявить их, но это обычно не очень хорошая идея. – Eric

0

попробовать это:

class Fruit: 
    name = '' 
    # remove this string facts = [] 
    def __init__(self, FruitName): 
     self.name = FruitName 
     self.facts = [] # add "self." 
    ... 

В вашем примере фактов является членом класса (не является членом экземпляра)

0

facts определяется как атрибут класса, то есть общий для всех экземпляров класса. Переместить назначение внутрь __init__:

def __init__(self, name): 
    self.name = name 
    self.facts = [] 

Кроме того, определение класса не кажется, что в нужном месте для хранения фактов, конечно, они должны быть аргументы addfact, где вы уже можете получить доступ к имени, используя self.name в любом случае:

def addfact(self, fact): 
    self.facts.append(fact) 
0

Существует разница между переменными класса и переменными экземпляра. Рассмотрим следующий пример:

>>> class Test: 
...  facts = [1] 
...  def __init__(self,v=None): 
...    if v: 
...      self.facts = v 
... 
>>> t = Test() 
>>> t.facts 
[1] 
>>> Test.facts 
[1] 
>>> Test.facts = [2] 
>>> t.facts 
[2] 
>>> t2 = Test([3]) 
>>> t.facts 
[2] 
>>> t2.facts 
[3] 
>>> Test.facts 
[2] 
>>> Test.facts = [4] 
>>> t.facts 
[4] 
>>> t2.facts 
[3] 

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

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