Додавання значення параметра за замовчуванням з підказкою типу в Python


236

Якщо у мене є така функція:

def foo(name, opts={}):
  pass

І я хочу додати параметри підказки типу, як це зробити? Те, як я припустив, дає мені синтаксичну помилку:

def foo(name: str, opts={}: dict) -> str:
  pass

Далі не випливає синтаксична помилка, але це не схоже на інтуїтивний спосіб вирішення цього випадку:

def foo(name: str, opts: dict={}) -> str:
  pass

Я не можу знайти нічого в typingдокументації або в пошуку Google.

Редагувати: Я не знав, як аргументи за замовчуванням працювали в Python, але заради цього питання я збережу приклади вище. Взагалі набагато краще зробити наступне:

def foo(name: str, opts: dict=None) -> str:
  if not opts:
    opts={}
  pass

4
Остання функція - правильний шлях. Це так само, як і scalaмова.
Israel Unterman

14
у вас є змінений тип за замовчуванням - це призведе до проблем
noɥʇʎԀʎzɐɹƆ

дивіться мою відповідь оновлення,
@josh

@ noɥʇʎԀʎzɐɹƆ Якщо тільки ви не використовуєте це, наприклад, запам'ятовування. : P
Mateen Ulhaq

Відповіді:


281

Ваш другий спосіб правильний.

def foo(opts: dict = {}):
    pass

print(foo.__annotations__)

це виводи

{'opts': <class 'dict'>}

Це правда, це не вказано в PEP 484 , але підказки типу - це застосування приміток до функцій, які задокументовані в PEP 3107. У розділі синтаксису ясно, що аргументи ключових слів таким чином функціонують з анотаціями функцій.

Я настійно не рекомендую використовувати мінливі аргументи ключових слів. Більше інформації тут .


1
Див. Legacy.python.org/dev/peps/pep-3107/#syntax . Підказки типу - це лише застосування приміток до функцій.
чепнер

@chepner правда. не знав, що PEP 3107 має щось щодо аргументів ключових слів.
noɥʇʎԀʎzɐɹƆ

2
Нічого собі, я не знав про змінні аргументи за замовчуванням в Python ... особливо це стосується Javascript / Ruby, де аргументи за замовчуванням працюють по-різному. Не збираюся переробити те, що вже було сказано ad nauseum навколо SO про це, я просто радий, що дізнався про це ще до того, як він мене покусав. Дякую!
Джош

6
Мені завжди рекомендували використовувати None, а не мутаційний тип на зразок {} або [] або об'єкт за замовчуванням, як мутації до цього об'єкта без глибокої копії зберігатимуться між ітераціями.
MrMesees

2
визначте достатньо функцій із змінними аргументами ключових слів, і це лише питання часу, перш ніж ви опинитесь на 4-годинній сесії налагодження, яка ставить під сумнів ваш життєвий вибір
Джозеф

20

Якщо ви використовуєте набір тексту (представлений у Python 3.5), ви можете використовувати typing.Optional, де Optional[X]еквівалентно Union[X, None]. Він використовується для сигналізації про те, що явне значення Noneдозволене. Від набору тексту. Необов’язково :

def foo(arg: Optional[int] = None) -> None:
    ...

2
Чи не повинно бути пробілів навколо =в, Optional[int] = Noneяк це умовно для аргументів ключових слів, що не натякають на тип?
фактична_панда

7

Нещодавно я бачив цей однопластовий:

def foo(name: str, opts: dict=None) -> str:
    opts = {} if not opts else opts
    pass

Привіт @Kirkalicious, дякую за вашу відповідь. Чи можете ви пояснити, як це працює?
Натан

1
Порожній дикт, що пройшов як параметр за замовчуванням, є однаковим для кожного виклику. Отже, якщо функція мутує її, то наступним разом за замовчуванням буде змінене значення за останній раз. Здійснення Noneза замовчуванням, а потім перевірка всередині методу дозволяє уникнути цієї проблеми, виділяючи новий dict кожен раз, коли метод викликається.
Ян Голдбі
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.