Як коментувати типи кількох повернених значень?


112

Як я можу використовувати підказки типу, щоб анотувати функцію, яка повертає значення, Iterableяке завжди дає два значення: a boolта a str? Підказка Tuple[bool, str]близька, за винятком того, що вона обмежує тип поверненого значення кортежем, а не генератором чи іншим типом ітерацій.

Мені в основному цікаво, оскільки я хотів би анотувати функцію, foo()яка використовується для повернення кількох значень, як це:

always_a_bool, always_a_str = foo()

Зазвичай такі функції, як foo()зробити щось на зразок return a, b(що повертає кортеж), але я хотів би, щоб підказка типу була досить гнучкою, щоб замінити повернутий кортеж генератором, списком або чимось іншим.



3
@ StevenM.Vascellaro Це не дублікат цього запитання
TWR Cole

Відповіді:


159

Ви завжди повертаєте один предмет; використання return one, twoпросто повертає кортеж.

Так що так, -> Tuple[bool, str]це цілком правильно.

ТількиTuple тип дозволяє задати фіксовану кількість елементів, кожен з яких з особливим типом. Ви дійсно повинні повертати кортеж, завжди, якщо ваша функція виробляє фіксовану кількість повернутих значень, особливо коли ці значення є конкретними, різними типами.

Очікується, що інші типи послідовностей мають одну специфікацію типу для змінної кількості елементів, тому typing.Sequenceтут не підходить. Також див. Яка різниця між списками та кортежами?

Кортежі є неоднорідними структурами даних (тобто їх записи мають різне значення), тоді як списки - однорідними послідовностями. Кортежі мають структуру, списки мають порядок.

Система підказок типу Python дотримується цієї філософії, в даний час не існує синтаксису, який би вказував ітерабель фіксованої довжини та містить конкретні типи в конкретних позиціях.

Якщо ви повинні вказати, що буде виконувати будь-який ітератор, найкраще, що ви можете зробити, це:

-> Iterable[Union[bool, str]]

в цей момент абонент може очікувати логічні значення та рядки в будь-якому порядку та невідомої довжини (десь від 0 до нескінченності).


2
Специфікація мови дозволяє повертати інші ітерабелі; foo()міг би робити yield True; yield "blah"і a, b = foo()все ще працював би. Або foo()може повернути список. Я переформулював своє запитання, щоб зрозуміти, що мені цікаво натякати на довільний ітератор, а не на кортеж.
Richard Hansen,

2
@RichardHansen: Я переглянув PEP та документацію typingта mypyще 2 рази з часу розміщення; Я впевнений, що нічого не пропустив. Тим не менш, на SO є кілька постійних користувачів з великою кількістю досвіду підказки типу Python, який не соромляться виправити мене, якщо виявиться помилковим, або надішле кращу відповідь.
Мартін Пітерс

21
Мені довелося додати, from typing import Tupleщоб анотація Tuple працювала.
PHPirate

3
@PHPirate: так, і вам доведеться зробити те саме для Iterableі Union. Оскільки ми обговорюємо тут їх конкретне використання, мається на увазі імпорт.
Мартін Пітерс

6
@MartijnPieters, дякую за чудову відповідь, але я думаю, що коментар PHPirate вартий редагування у вашій оригінальній відповіді.
Тім Міронов,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.