Python: словарь как переменная экземпляра

Возможный дубликат:
«Наименьшее удивление» в Python: аргумент Mutable Default

Я очень смущен поведением словарей как переменных экземпляра класса в Python 3. Как я понимаю, переменные экземпляра в Python имеют хранилище на каждом экземпляре , в отличие от переменных класса, которые являются per-class (подобно тому, как говорят некоторые другие языки "статический").

И, похоже, это верно, за исключением случаев, когда переменная экземпляра является словарем, созданным из параметра по умолчанию. Например:

class Foo: def __init__(self, values = dict()): self.values = values f1 = Foo() f1.values["hello"] = "world" f2 = Foo() print(f2.values) 

Эта программа выводит:

 {'hello': 'world'} 

А? Почему экземпляр f2 имеет тот же экземпляр словаря, что и f1 ?

Я получаю ожидаемое поведение, если я не перехожу в пустой словарь в качестве параметра по умолчанию и просто присваиваю self.values пустому словарю явно:

 class Foo: def __init__(self): self.values = dict() 

Но я не понимаю, почему это должно иметь значение.

2 Solutions collect form web for “Python: словарь как переменная экземпляра”

Это хорошо известный сюрприз в Python. Параметры по умолчанию оцениваются, когда функция определена, а не когда она вызывается. Таким образом, ваш параметр по умолчанию является ссылкой на общий dict . Он не имеет ничего общего с назначением переменных класса / экземпляра.

Если вы хотите использовать параметр по умолчанию, используйте « None и проверьте его:

 if values is None: self.values = {} else: self.values = values 

Значения по умолчанию оцениваются только один раз. Вы хотите что-то вроде этого:

  class Foo: def __init__(self, values = None): self.values = values or dict() 

Если вы укажете values , которые будут использоваться. Если нет, values оцениваются как FALSE оператором or и создают новый dict.

  • Основной вопрос импорта Python
  • В этой ситуации Python 3 не нуждается в __init__.py?
  • При использовании cx_Freeze и tkinter я получаю: «Ошибка загрузки DLL: указанный модуль не найден». (Python 3.5.3)
  • Отображение колб в отдельном модуле
  • был ли Python 3 широко принят?
  • Постройте график, очистите его оси, затем постройте новый график
  • Как сделать таблицу на Python 3.5.2?
  • Анализ всех XML-файлов в каталоге и всех подкаталогах
  • Python - лучший язык программирования в мире.