Наилучшая практика для установки значения по умолчанию параметра, который должен быть списком в Python? - PullRequest
63 голосов
/ 02 марта 2012

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

def func(items=[]):
    print items

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

Ответы [ 4 ]

85 голосов
/ 02 марта 2012

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

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

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

8 голосов
/ 17 сентября 2013

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

  def func(items=()):
      print items

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

3 голосов
/ 02 марта 2012

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

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

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

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

1 голос
/ 02 марта 2012

Кроме того, а также, чтобы лучше понять, что такое 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]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...