значение как атрибута в классе в python

#python #class

#python #класс

Вопрос:

 from collections import deque
class testClass:
  def __init__(self):
    self.a = deque()
    self.c = deque()
    self.a.append(1)
    self.c.append(2)

  def testFunc1(self):
    self.b = self.a
    self.a = self.c
    self.c = self.b
    print(self.b.pop())

  def testFunc2(self):
    self.b = self.a
    self.a = self.a.append(10)
    print(self.b.pop())

TestInstance = testClass()
TestInstance.testFunc1() #answer will be 1
TestInstance.testFunc2() #answer will be 10
  

Я просто не понимаю, почему два ответа разные. Обе функции сначала присваиваются self.a self.b . Из результатов мы можем видеть, что если мы посмотрим на testFunc2 , self.b изменится, если self.a изменится. Однако, если мы посмотрим на testFunc1 , self.b не изменится, если self.a изменится. Почему это произошло? Кто-нибудь может мне объяснить?

Комментарии:

1. self.b изменилось бы, если бы значение deque, на которое первоначально указывал self.a (на которое теперь ссылается self.c ), изменилось. Вероятно, вам следует прочитать nedbatchelder.com/text/names.html чтобы понять, что на самом деле означают все эти назначения.

2. спасибо за ваш ответ. я только что нашел другой веб-сайт, который мог бы визуализировать коды python. Я нахожу чрезвычайно полезным разобраться в вопросах такого типа, как мой.

3. забыл добавить ссылку. Веб-сайт, упомянутый выше, является pythontutor.com/visualize.html

Ответ №1:

Ключ в том, чтобы знать, на что deque ссылается каждый атрибут после каждого присвоения.

После __init__ выполнения у вас есть два значения deque; допустим, это self.a относится к d1 и self.c ссылается на d2 . Затем d1 содержит число 1 и d2 содержит число 2.

При testFunc1 вызове self.b создается ссылка на d1 . Затем self.a изменяется на ссылку на d2 , а затем self.c создается ссылка на d1 . Последняя строка удаляет значение из d1 и печатает его, выводя 1.

При testFunc2 запуске self.a по-прежнему ссылается на d2 и self.b , и self.c оба ссылаются на d1 . Первое присвоение делает self.b ссылку на d2 . Следующее присваивание добавляет 10 к d2 , но затем делает self.a ссылку на None , поскольку это то, что deque.append возвращает (не само обновленное deque ). self.b.pop() немедленно удаляет 10, которые мы только что добавили к d2 , и это значение печатается.

Комментарии:

1. спасибо за ваше объяснение. Думаю, я понял, что вы сказали, но все же хочу уточнить у вас одну вещь. После первого присваивания в testFunc2 оба self.a и self.b ссылаются на d2 . self.a.append(10) добавит 10 к d2 , но вернет None . Следовательно, второе присвоение self.a = self.a.append(10) заставит self.a указывать на другой объект (который является None ). В то же время, self.b все еще указывает на d2 (который только что добавлен 10 ). Правильно ли я понимаю? Еще раз спасибо!

2. Именно так.

3. Отлично! Спасибо!

Ответ №2:

Проблема в том self.b = self.a . Используя оператор =, вы думаете, что это создает новый объект; на самом деле это не так. Это только создает новую переменную, которая разделяет ссылку на исходный объект. Когда вы изменяете self.a , добавляя другой элемент, self.b изменения также происходят, потому что они указывают на одно и то же. Используйте copy() или deepcopy() в зависимости от того, что вам нужно. Для этого примера, я думаю, copy() достаточно.

измените self.b = self.a на self.b = copy.copy(self.a) , вы получите то, что ожидаете. Пожалуйста, не забудьте import copy .

Подробнее читайте copy в Python.