Я только что недавно совершил ошибку в Python. Это был один из тех глупых ошибок новичка, но он заставил меня задуматься о механизмах Python (я долго программист на C++, новый для Python). Я выложу код ошибки и объясню, что я сделал, чтобы исправить это, а затем у меня есть несколько вопросов ...Инициализация членов класса Python
Сценарий: У меня есть класс под названием A, в котором есть член данных словаря, его код (это упрощение, конечно):
class A:
dict1={}
def add_stuff_to_1(self, k, v):
self.dict1[k]=v
def print_stuff(self):
print(self.dict1)
класс с использованием этого кода класса B:
class B:
def do_something_with_a1(self):
a_instance = A()
a_instance.print_stuff()
a_instance.add_stuff_to_1('a', 1)
a_instance.add_stuff_to_1('b', 2)
a_instance.print_stuff()
def do_something_with_a2(self):
a_instance = A()
a_instance.print_stuff()
a_instance.add_stuff_to_1('c', 1)
a_instance.add_stuff_to_1('d', 2)
a_instance.print_stuff()
def do_something_with_a3(self):
a_instance = A()
a_instance.print_stuff()
a_instance.add_stuff_to_1('e', 1)
a_instance.add_stuff_to_1('f', 2)
a_instance.print_stuff()
def __init__(self):
self.do_something_with_a1()
print("---")
self.do_something_with_a2()
print("---")
self.do_something_with_a3()
Обратите внимание, что каждый вызов do_something_with_aX()
инициализирует новый «чистый» экземпляр класса А, и печатает словарь до и после добавления.
Исправлена ошибка (в случае, если вы еще не поняли его еще нет):
>>> b_instance = B()
{}
{'a': 1, 'b': 2}
---
{'a': 1, 'b': 2}
{'a': 1, 'c': 1, 'b': 2, 'd': 2}
---
{'a': 1, 'c': 1, 'b': 2, 'd': 2}
{'a': 1, 'c': 1, 'b': 2, 'e': 1, 'd': 2, 'f': 2}
Во второй инициализации класса А, словари не являются пустыми, но начинают с содержимым последней инициализации, и так далее. Я ожидал, что они начнут «свежие».
Что решает эту «ошибку», очевидно, добавив:
self.dict1 = {}
В __init__
конструктор класса А. Однако, что заставило меня задаться вопросом:
- Что такое значение «dict1 = {} "в точке объявления dict1 (первая строка в классе A)? Это бессмысленно?
- Каков механизм создания экземпляра, который вызывает копирование ссылки с последней инициализации?
- Если я добавлю «self.dict1 = {}» в конструкторе (или любом другом элементе данных), как это не повлияет на член словаря ранее инициализированных экземпляров?
EDIT: После ответов Теперь я понимаю, что, объявляя элемент данных и не обращаясь к нему в __init__
или где-то еще, как self.dict1, я практически определение того, что называется в C++/Java статический член данных. Называя его self.dict1, я делаю его «привязанным к экземпляру».
Вы должны использовать классы нового стиля, полученные из объекта. – nikow