Предоставьте OrderedSet [int] подобные типы, используя стаб-файл без изменения библиотеки упорядоченных наборов - PullRequest
0 голосов
/ 29 сентября 2018

Я добавил подсказки типа для упорядоченного набора библиотеки.Проблема в том, что, несмотря на то, что в файле ordered_set.pyi есть следующие строки:

from typing import MutableSet, TypeVar, Sequence

T = TypeVar('T')

class OrderedSet(MutableSet[T], Sequence[T]):
    ...

Я не могу написать:

IntOrderedSet = OrderedSet[int]

в моем коде, Python вызывает:

TypeError: 'ABCMeta' object is not subscriptable

Это происходит потому, что в ordered_set.py OrderedSet определяется как:

from collections.abc import MutableSet, Sequence

class OrderedSet(MutableSet, Sequence):
    ...

Я сделал PR с коммитом, который изменяет OrderedSet class для наследования от набора классов , но владелец ordered-set отказался принять его, потому что, как он сказал:

Импорт набора текста внутри кода добавляет зависимость времени установки и стоимость времени выполнения кода.упорядоченный_сет получен как единый модуль без зависимостей в течение 6 лет.Кто-то может решить, что он не хочет иметь ничего общего с setuptools, и просто сбросить order_set на своей PYTHONPATH, и это все равно будет работать.Я бы не хотел потерять это из-за типов.

Есть ли способ поддержки OrderedSet[int] подобных типов без изменения файла библиотеки ordered_set.py?

1 Ответ

0 голосов
/ 29 сентября 2018

Единственный обходной путь, о котором я знаю, - это определить любые псевдонимы пользовательских типов так, чтобы они существовали только во время проверки типа, а не во время выполнения.

Для этого выпотребуется:

  1. Определить псевдонимы любого типа внутри if typing.TYPE_CHECKING: блоков.Блок typing.TYPE_CHECKING всегда имеет значение false во время выполнения и считается проверяющим типом как true.
  2. Убедитесь, что у вас либо все ваши подсказки типа, что и строки, или, если вы используете Python 3.7,добавить from __future__ import annotations, который делает это автоматически.То есть, во-первых, не нужно когда-либо оценивать подсказки типов.

Так, например, в вашей конкретной настройке вы можете добавить заглушки для библиотеки OrderedSet где-нибудь, а затем написать свой код, чтобы он выглядел следующим образом(предположим, Python 3.7 +):

from __future__ import annotations
from typing import TYPE_CHECKING
from ordered_set import OrderedSet

# Basically equivalent to `if False`
if TYPE_CHECKING:
    IntOrderedSet = OrderedSet[Int]

def expects_int_ordered_set(x: IntOrderedSet) -> None:
    # blah

some_ordered_set: IntOrderedSet = OrderedSet()

Или, если вы используете Python 3.6 или ниже:

from typing import TYPE_CHECKING
from ordered_set import OrderedSet

if TYPE_CHECKING:
    IntOrderedSet = OrderedSet[Int]

def expects_int_ordered_set(x: 'IntOrderedSet') -> None:
    # blah

some_ordered_set: 'IntOrderedSet' = OrderedSet()

Если вы в порядке немного врать, мы могли бы отказатьсясо строкой вещи и определите IntOrderedSet, чтобы немного отличаться во время проверки типа от времени выполнения.Например:

from typing import TYPE_CHECKING
from ordered_set import OrderedSet

if TYPE_CHECKING:
    IntOrderedSet = OrderedSet[Int]
else:
    IntOrderedSet = OrderedSet

def expects_int_ordered_set(x: IntOrderedSet) -> None:
    # blah

some_ordered_set = IntOrderedSet()

Будьте осторожны, когда вы делаете это, хотя - средство проверки типов не проверяет ничего в блоке 'else' / не проверяет, чтобы убедиться, что выто, что вы делаете, согласуется с тем, что находится в блоке if TYPE_CHECKING.

Окончательное решение состоит в том, чтобы просто не определять тип IntOrderedSet в первую очередь.Это позволяет нам пропустить хак 1, при этом нужно всего лишь использовать хак 2 (что не так уж много взлома - это будет поведение по умолчанию в Python через несколько лет).

Так, например, мы могли бы сделать это:

from __future__ import annotations
from ordered_set import OrderedSet

def expects_int_ordered_set(x: OrderedSet[int]) -> None:
    # blah

some_ordered_set: OrderedSet[int] = OrderedSet()

В зависимости от контекста, может случиться, что мне даже не нужно добавлять аннотацию к этому последнему объявлению переменной.Здесь мы это делаем, но если бы мы определяли эту переменную внутри функции, вполне возможно, что средства проверки типов, такие как mypy, автоматически выведут для нас правильный тип в зависимости от того, как мы в итоге будем использовать эту переменную.

...