Різниця між визначенням набору тексту.


102

Я практикую використання підказок типу в Python 3.5. Один з моїх колег використовує typing.Dict:

import typing


def change_bandwidths(new_bandwidths: typing.Dict,
                      user_id: int,
                      user_name: str) -> bool:
    print(new_bandwidths, user_id, user_name)
    return False


def my_change_bandwidths(new_bandwidths: dict,
                         user_id: int,
                         user_name: str) ->bool:
    print(new_bandwidths, user_id, user_name)
    return True


def main():
    my_id, my_name = 23, "Tiras"
    simple_dict = {"Hello": "Moon"}
    change_bandwidths(simple_dict, my_id, my_name)
    new_dict = {"new": "energy source"}
    my_change_bandwidths(new_dict, my_id, my_name)

if __name__ == "__main__":
    main()

Обидва вони працюють чудово, різниці, здається, немає.

Я прочитав typingдокументацію до модуля .

Між тим typing.Dictчи dictякий із них слід використовувати в програмі?


11
Зверніть увагу, що Python насправді не застосовує підказки щодо типів. Вони є лише підказками , вони не використовуються під час виконання або навіть під час компіляції для встановлення типів. Python може бути сильно набраний (на противагу слабкому набору тексту), він також динамічно набраний (на противагу суворому набору тексту). Див. Чи набирається Python міцно? . Зовнішні інструменти, такі як mypy, можуть використовувати ці підказки, щоб допомогти вам написати кращий код, однак, у процесі, який називається статичним аналізом.
Мартін Пітерс

1
@MartijnPieters Я раніше любив використовувати підказки типу в своєму коді поряд з MyPy і робити вигляд, що можу використовувати Python із захистом типу. На жаль, це принесло мені А) код, який не працює на <3,4 та Б) люди сміються з мене, бо, мабуть, підказки типу - це насмішка. Це справді досить прикро.
кішка

3
@cat: Натяк на тип було введено в Python співробітником Facebook, оскільки ми мали величезний успіх, додавши ту саму функцію до PHP (див. hack ). Той, хто сміється, ніколи не будував великого проекту з кількома інженерами.
Мартін Пітерс

3
@MartijnPieters Ні, def a(b: int) -> bool:це синтаксична помилка в Python 2.7, і я думаю, що це синтаксична помилка і в старих версіях Python 3.
кішка

1
@cat: ви тут говорите про анотації функцій , синтаксис, який був доданий до Python 3.0. Отже, єдиною версією, де це синтаксична помилка, є 2.7, саме тому mypy підтримує розміщення цієї інформації в коментарях.
Мартін Пітерс

Відповіді:


139

Немає реальної різниці між використанням рівнини typing.Dictта dict, ні.

Тим НЕ менше, typing.Dictце тип Generic , який дозволяє вказати тип ключів і значень теж , що робить його більш гнучким:

def change_bandwidths(new_bandwidths: typing.Dict[str, str],
                      user_id: int,
                      user_name: str) -> bool:

Таким чином, цілком може статися так, що в якийсь момент у житті вашого проекту ви хочете дещо точніше визначити аргумент словника, в цей момент розширення typing.Dictдо typing.Dict[key_type, value_type]є "меншою" зміною, ніж заміна dict.

Ви можете зробити це ще більш загальним, використовуючи Mappingабо MutableMappingтипи тут; оскільки вашій функції не потрібно змінювати відображення, я б дотримувався Mapping. A dict- одне відображення, але ви можете створити інші об'єкти, які також задовольняють інтерфейс відображення, і ваша функція цілком може працювати з цими:

def change_bandwidths(new_bandwidths: typing.Mapping[str, str],
                      user_id: int,
                      user_name: str) -> bool:

Тепер ви чітко розповісти іншим користувачам цієї функції , що ваш код не буде фактично змінюють на new_bandwidthsвідображення передається в.

Ваша реальна реалізація - це просто очікування об’єкта, який можна надрукувати. Це може бути тестовою реалізацією, але в такому вигляді ваш код продовжуватиме працювати, якщо ви використовували new_bandwidths: typing.Any, оскільки будь-який об’єкт у Python є для друку.


2
Додатковими корисними прикладами можуть бути випадки, коли значення словника можуть бути різних типів, наприклад {"name": "bob", "age" : 51}, це може бути щось подібне typing.Mapping[Union[str, int]? А як щодо вкладеного словника, як {"person": {"name":"bob", "age": 51}би це було щось подібне typing.Mapping[str, typing.Mapping[Union[str, int]]? Використання Unionподібного мене турбує, оскільки це не сувора схема, оскільки немає впорядкування. Можливо, це нормально, або є альтернатива?
Давос,

1
Не дивлячись на Unionпитання, я бачу, що це все ще відкрите обговорення github.com/python/typing/issues/28
Давос,

1
Це видається дуже цікавим, корисним та пов’язаним з ним python.org/dev/peps/pep-0589
Грег Хілстон,

@GregHilston: це насправді про те, як обмежити, які ключі може містити словник, і вказати, які типи має мати кожне пов'язане значення.
Мартін Пітерс

1
@GregHilston: ах, так, це так.
Мартін Пітерс

26

typing.Dictє загальною версією dict:

class typing.Dict(dict, MutableMapping[KT, VT])

Загальна версія дикту. Використання цього типу полягає в наступному:

def get_position_in_index(word_list: Dict[str, int], word: str) -> int:
     return word_list[word]

Тут ви можете вказати тип ключа та значення в дикті: Dict[str, int]

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