Лучшая практика для установки значения по умолчанию параметра, который должен быть списком в Python?
У меня есть функция Python, которая принимает список в качестве параметра. Если я установлю значение параметра по умолчанию в пустой список, как это:
def func(items=[]):
print items
Pylint сказал бы мне "опасное значение по умолчанию [] в качестве аргумента". Поэтому мне было интересно, какая здесь лучшая практика?
4 ответа:
использовать
None
в качестве значения по умолчанию:def func(items=None): if items is None: items = [] print items
проблема с изменяемым аргументом по умолчанию заключается в том, что он будет разделен между всеми вызовами функции-см. "важное предупреждение" в соответствующий раздел учебника Python.
Я только что столкнулся с этим в первый раз, и моя непосредственная мысль: "Ну, я все равно не хочу мутировать список, поэтому я действительно хочу по умолчанию использовать неизменяемый список, поэтому Python даст мне ошибку, если я случайно мутирую его."Неизменяемый список-это просто кортеж. Итак:
def func(items=()): print itemsконечно, если вы передадите его чему-то, что действительно хочет список (например, isinstance(items, list)), то это приведет вас к неприятностям. Но это все равно кодовый запах.
для изменяемого объекта в качестве параметра по умолчанию в объявлениях функций и методов проблема заключается в том, что оценка и создание происходят в один и тот же момент. Python-parser читает function-head и оценивает его в тот же момент.
большинство начинающих считают, что новый объект создается при каждом вызове, но это не так! Один объект (в вашем примере список) создается в момент объявления, а не по требованию, когда вы вызываете метод.
для imutable объектов это не проблема, потому что даже если все вызовы имеют один и тот же объект, он является imutable и поэтому его свойства остаются неизменными.
в качестве соглашения вы используете
None
объект для значений по умолчанию указывает на использование инициализации по умолчанию, которая теперь может иметь место в теле функции, которое, естественно, вычисляется во время вызова.
кроме того, а также чтобы лучше понять, что такое python, вот мой маленький тематический фрагмент:
from functools import wraps def defaultFactories(func): 'wraps function to use factories instead of values for defaults in call' defaults = func.func_defaults @wraps(func) def wrapped(*args,**kwargs): func.func_defaults = tuple(default() for default in defaults) return func(*args,**kwargs) return wrapped def f1(n,b = []): b.append(n) if n == 1: return b else: return f1(n-1) + b @defaultFactories def f2(n,b = list): b.append(n) if n == 1: return b else: return f2(n-1) + b >>> f1(6) [6, 5, 4, 3, 2, 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, 3, 2, 1] >>> f2(6) [1, 2, 3, 4, 5, 6]