Должны ли классы импортироваться, когда они используются только для подсказок типов?ПКП 560 - PullRequest
0 голосов
/ 22 ноября 2018

В чем выгода импорта from __future__ import annotations?Когда я правильно понимаю, я должен прекратить ненужный импорт ввода во время выполнения.

В моем примере HelloWorld требуется только для набора текста.Но с этим кодом вывод всегда будет:

Should this happen? x = World!

Когда я удаляю from hello import HelloWorld, справка по вводу в PyCharm больше не работает (я могу понять это, потому что не понимаетоткуда HelloWorld от).

from __future__ import annotations

from hello import HelloWorld

if __name__ == '__main__':
    def hello(x: str, hello: HelloWorld = None):
        if hello is not None:
            print('hello.data_01 =', hello.data_01)
        print('x =', x)


    hello('World!')

hello.py

from dataclasses import dataclass


@dataclass
class HelloWorld:
    data_01: str
    data_02: str


print("Should this happen?")

Поэтому мой вопрос заключается в том, нужно ли мне делать from hello import HelloWorld какие преимущества я получу от from __future__ import annotations

1 Ответ

0 голосов
/ 24 ноября 2018

Импорт from __future__ import annotations имеет одно основное преимущество: он позволяет использовать прямые ссылки очиститель.

Например, рассмотрим эту (в настоящее время неработающую) программу.

# Error! MyClass has not been defined yet in the global scope
def foo(x: MyClass) -> None:
    pass

class MyClass:
    # Error! MyClass is not defined yet, in the class scope
    def return_copy(self) -> MyClass:
        pass

Эта программа на самом деле вылетает , когда вы пытаетесь запустить ее во время выполнения: вы пытались использовать 'MyClass' до того, как он вообще когда-либо будет определен.Чтобы исправить это раньше, вам пришлось либо использовать синтаксис комментариев типа, либо обернуть каждый 'MyClass' в строку, чтобы создать прямую ссылку :

def foo(x: "MyClass") -> None:
    pass

class MyClass:
    def return_copy(self) -> "MyClass":
        pass

Хотя это работаетЧувствую себя очень вяло.Типы должны быть типами: нам не нужно вручную преобразовывать определенные типы в строки только для того, чтобы типы хорошо воспроизводились во время выполнения Python.

Мы можем исправить это, добавив from __future__ import annotations import: эту строкуавтоматически заставляет все печатать строку во время выполнения.Это позволяет нам писать код, который выглядит как первый пример, без сбоев: поскольку каждый тип подсказки является строкой во время выполнения, мы больше не ссылаемся на то, что еще не существует.

И проверки типов, такие как mypyили Pycharm не будет заботиться: для них тип выглядит одинаково независимо от того, как Python сам выбирает его для представления.


Следует отметить, что этот импорт сам по себе не позволяетИзбегайте импорта вещей.Это просто делает его чище при этом.

Например, рассмотрим следующее:

from expensive_to_import_module import MyType

def blah(x: MyType) -> None: ...

Если expensive_to_import_module выполняет много логики запуска, это может означать, что он не требуетнезначительное количество времени для импорта MyType.Это не будет иметь большого значения, когда программа действительно будет запущена, но делает , замедляя время запуска.Это может быть особенно неприятно, если вы пытаетесь написать недолговечные программы в стиле командной строки: добавление подсказок типа иногда может заставить вашу программу чувствовать себя более вялой при запуске.

Мы могли бы исправьте это, сделав MyType строку, скрывая импорт за if TYPE_CHECKING охранником, например:

from typing import TYPE_CHECKING

# TYPE_CHECKING is False at runtime, but treated as True by type checkers.
# So the Python interpreters won't do the expensive import, but the type checker
# will still understand where MyType came from!
if TYPE_CHECKING:
    from expensive_to_import_module import MyType

# This is a string reference, so we don't attempt to actually use MyType
# at runtime.
def blah(x: "MyType") -> None: ...

Это работает, но снова выглядит неуклюже.Зачем нам нужно добавлять кавычки вокруг последнего типа?annotations импорт в будущем делает синтаксис для этого немного более плавным:

from __future__ import annotations
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from expensive_to_import_module import MyType

# Hooray, no more quotes!
def blah(x: MyType) -> None: ...

В зависимости от вашей точки зрения, это может не показаться огромным выигрышем.Но это делает намного более эргономичным использование подсказок типов, заставляет их чувствовать себя более «интегрированными» в Python, и (как только они становятся включенными по умолчанию) удаляет общий камень преткновения для новичков в PEP 484, как правило, опрокидывается,

...