Python - Как правильно скопировать объект класса A, который содержит массив объектов класса B - PullRequest
0 голосов
/ 19 июня 2020

Я хочу скопировать массив объектов класса и обновить исходный массив без изменения скопированного массива. См. Этот код, который иллюстрирует проблему. Я не хочу, чтобы B изменялся при изменении A:

Копировать массив объектов класса test

import copy

class B:
  val=0
  p=40

class A:
  g=[]

  def __init__(self):
      self.g.append(B())
      self.g.append(B())                                                       
        
def main():
  a=A()
  print("a.g[0] is " + str(a.g[0].val) + " , " + str(a.g[0].p))
  print("a.g[1] is " + str(a.g[1].val) + " , " + str(a.g[1].p))
  print("Copying a to b")
  b=copy.deepcopy(a)
  print ("Now updating a[0]")
  a.g[0].val=25
  print("a.g[0] now is " + str(a.g[0].val) + " , " + str(a.g[0].p))
  print("a.g[1] now is " + str(a.g[1].val) + " , " + str(a.g[1].p))
  print("Now printing which which was copied from original a")
  print("b.g[0] is " + str(b.g[0].val) + " , " + str(b.g[0].p))
  print("b.g[1] is " + str(b.g[1].val) + " , " + str(b.g[1].p))


if __name__ == "__main__":
  main()
    

1 Ответ

1 голос
/ 19 июня 2020

Проблема в том, что вы определяете val, p и g как переменные класса, объявляя их непосредственно внутри класса.

Когда вы объявляете переменную класса, эта переменная связана непосредственно с самим классом и влияет на все экземпляры класса. Переменная экземпляра создается со всеми объектами этого класса, но значение может варьироваться от объекта к объекту. Представьте себе класс с именем wallet с атрибутом money. Каждый wallet начинается с 1000 для денег, но они выигрывают и теряют деньги независимо друг от друга. Если я добавлю 100 к одному wallet, все остальные изменятся. Переменная класса ведет себя иначе. Допустим, я дал wallet переменную класса с именем currency и установил для нее значение "USD". Если я изменю эту переменную на "CAD", теперь ВСЕ объекты wallet будут иметь свой атрибут currency, установленный на "CAD", включая те, которые уже созданы.

Решение состоит в том, чтобы сделать их экземплярами переменные и присвоение значений под __init__ как self.<insert>, а не просто <insert>. Вы можете увидеть пример изменения ниже. Когда я запустил вашу функцию main() с изменениями, внесенными в классы ниже, изменения, внесенные в A, не были отражены в B.

Хорошее практическое правило - всегда по умолчанию объявлять ваши переменные внутри __init__, потому что это заставит вас задуматься о том, как ведет себя переменная класса, когда вы ее используете.

class B:
    def __init__(self):
        self.val=0
        self.p=40

class A:
    def __init__(self):
        self.g=[]
        self.g.append(B())
        self.g.append(B())       
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...