Идиоматический питон, управление аргументами по умолчанию в функциях

Я обычно сталкиваюсь с тем, что большинство людей управляют значениями аргументов по умолчанию в функциях или методах следующим образом:

def foo(L=None):
  if L is None:
    L = []

Однако я вижу, что другие люди делают что-то вроде:

def foo(L=None):
  L = L or []

Я не знаю, если что-то упустил, но почему большинство людей используют первый подход вместо второго? Одинаково ли они одно и то же? Кажется, что второе яснее и короче.

3 ответа

Решение

Они не равны. Первый подход проверяет, что именно задано L является None, Во-вторых, проверяется, что L истинно в Python. В Python, если вы проверяете список условий, правила следующие:

  1. Список пуст, значит Ложь
  2. Правда иначе

Так в чем же разница между упомянутыми подходами? Сравните этот код.

Первый:

def foo(L=None):
    if L is None:
        L = []
    L.append('x')
    return L

>>> my_list = []
>>> foo(my_list)
>>> my_list
['x']

Во-вторых:

def foo(L=None):
    L = L or []
    L.append('x')
    return L

>>> my_list = []
>>> foo(my_list)
>>> my_list
[]

Так что сначала не создавайте новый список, он использовал данный список. Но второй создает новый.

Эти два значения не эквивалентны, если аргумент имеет значение false-y. Это не имеет большого значения, так как многие значения false-y не являются подходящими аргументами для большинства функций, где вы делаете это. Тем не менее, существуют мыслимые ситуации, в которых это может иметь значение. Например, если функция должна заполнять словарь (создавая новый, если ничего не задано), и вместо этого кто-то пропускает пустой упорядоченный словарь, то последний подход неправильно возвращает обычный словарь.

Это не моя основная причина всегда использовать is None версия хотя. Я предпочитаю это, поскольку это более явно и тот факт, что or возвращает один из его операндов не интуитивно для меня. Мне нравится забывать об этом так долго, как я могу;-) Дополнительная строка не проблема, это относительно редко.

Может быть, они не знают о втором? Я склонен использовать первое.

На самом деле есть разница. Второй позволит L = [], если вы передадите что-либо, что оценивается как Boolean false. 0 пустая строка или другие. Первый будет делать это только в том случае, если L не передан или был передан как None.

Другие вопросы по тегам