IDE предупреждение о непостоянном аргументе по умолчанию и бесполезном автоматическом исправлении? - PullRequest
0 голосов
/ 11 февраля 2019

Когда я пишу следующий код, моя IDE предупреждает о «изменяемом аргументе по умолчанию»:

VALUES = [ 1, 2, 3 ]

def f(values=VALUES):
  print(values)

Вместо этого предлагается написать следующее:

VALUES = [ 1, 2, 3 ]

def f(values=None):
  if values is None:
    values = VALUES
  print(values)

Конечно, этоизбегает иметь (изменяемый) список в качестве аргумента по умолчанию, и моя IDE больше не жалуется.Кажется, это улучшение.

Но с другой стороны, каков был первоначальный риск?Первоначальный риск состоял в том, что f() может изменить список в своем коде, например, так:

VALUES = [ 1, 2, 3 ]

def f(values=VALUES):
  values.append(4)
  print(values)

Это могло бы изменить значение VALUES навсегда (то есть не только локально), а затем вызыватьf() все равно будет иметь измененное значение по умолчанию, которое, вероятно, не предназначено.Кроме того, учитывая код выше, VALUES будет расти на один 4 с каждым вызовом f().Таким образом, эта ситуация, вероятно, будет не такой, как задумано, если только values в f() не изменится, что сложно реализовать.

Но решает ли проблема предложенное IDE "исправление"?

Я думаю, что не потому, что если бы код f() теперь содержал values.append(4), то же самое произошло бы снова:

def f(values=None):
  if values is None:
    values = VALUES
  values.append(4)
  print(values)

Опять же, каждый вызов увеличил бы VALUES на один 4.

Реальное исправление было бы следующим:

def f(values=None):
  if values is None:
    values = VALUES.copy()  # or VALUES[:] or similar
  values.append(4)
  print(values)

Но это IDE не предлагает и, конечно, это будет дорого, потому что копии создаются каждый раз.

Другие вопросы уже связаны с этой проблемой (например, Почему использование None устраняет проблему изменяемого аргумента Python по умолчанию? ), но в этом тикете они используют не такую ​​константу, как VALUES, а литерал [], который создаетновое значение при каждом выполнении кода, поэтому оно похоже на подход .copy().

Теперь вопросы:

Почему в любой среде IDE это исправление предлагается (в данном случае сконстанта)?Возможно ли это исправить другие аспекты этой проблемы, о которых я не задумывался?

Есть ли лучший способ исправить исходную проблему, в которой нет хотя бы одной из двух проблем (значение по умолчанию может изменитьсянеожиданно, ② дорогостоящее копирование значения)?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...