Подтвердить что ты не робот

Лучшая практика для установки значения по умолчанию для параметра, который должен быть списком в Python?

У меня есть функция Python, которая принимает список как параметр. Если я установил значение по умолчанию для параметра в пустой список, например:

def func(items=[]):
    print items

Пилинт скажет мне "Опасное значение по умолчанию [] как аргумент". Поэтому мне было интересно, что здесь лучше всего?

4b9b3361

Ответ 1

Используйте None как значение по умолчанию:

def func(items=None):
    if items is None:
        items = []
    print items

Проблема с изменяемым аргументом по умолчанию заключается в том, что он будет разделяться между всеми вызовами функции - см. "важное предупреждение" в соответствующем разделе учебника Python.

Ответ 2

Я впервые столкнулся с этим в первый раз, и моя непосредственная мысль "ну, я все равно не хочу мутировать список, так что я действительно хочу, чтобы по умолчанию был неизменный список, поэтому Python даст мне ошибку если я случайно мутирую его". Неизменяемый список - это всего лишь кортеж. Итак:

  def func(items=()):
      print items

Конечно, если вы передадите его тому, что действительно хочет список (например, isinstance (items, list)), тогда это вызовет у вас проблемы. Но что-то запах кода в любом случае.

Ответ 3

Для изменяемого объекта в качестве параметра по умолчанию в описании функций и методов проблема заключается в том, что оценка и создание происходит точно в тот же момент. Python-парсер считывает функцию-head и оценивает ее в тот же момент.

Большинство начинающих считают, что новый объект создается при каждом вызове, но это неверно! Один объект (в вашем примере список) создается в момент ДЕКЛАРАЦИИ, а не по требованию, когда вы вызываете метод.

Для imutable объектов, которые не являются проблемой, потому что, даже если все вызовы имеют один и тот же объект, он может быть imutable и поэтому свойства остаются неизменными.

В качестве соглашения вы используете объект None для значений по умолчанию для указания использования инициализации по умолчанию, которая теперь может выполняться в теле функции, которая, естественно, оценивается во время вызова.

Ответ 4

Кроме того, чтобы лучше понять, что такое 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]