Тип Pycharm подсказывает предупреждение для классов вместо экземпляров - PullRequest
0 голосов
/ 22 октября 2019

Я пытаюсь понять, почему pycharm предупреждает меня о неправильном типе при использовании реализации абстрактного класса со статическим методом в качестве параметра.

Чтобы продемонстрировать, я приведу простой пример. Допустим, у меня есть абстрактный класс с одним методом, класс, который реализует (наследует) этот интерфейсный класс, и метод, который получает реализацию, которую он должен использовать в качестве параметра.

import abc


class GreetingMakerBase(abc.ABC):
    @abc.abstractmethod
    def make_greeting(self, name: str) -> str:
        """ Makes greeting string with name of person """


class HelloGreetingMaker(GreetingMakerBase):
    def make_greeting(self, name: str) -> str:
        return "Hello {}!".format(name)


def print_greeting(maker: GreetingMakerBase, name):
    print(maker.make_greeting(name))

hello_maker = HelloGreetingMaker()
print_greeting(hello_maker, "John")

Обратите внимание, что вподсказка типа print_greeting Я использовал GreetingMakerBase, и потому что isinstance(hello_maker, GreetingMakerBase) is True Pycharm не жалуется на это.

Проблема в том, что у меня много реализаций моего класса, и я не хочу делать экземпляркаждый, поэтому я сделаю этот метод make_greeting статическим, например:

class GreetingMakerBase(abc.ABC):
    @staticmethod
    @abc.abstractmethod
    def make_greeting(name: str) -> str:
        """ Makes greeting string with name of person """


class HelloGreetingMaker(GreetingMakerBase):
    @staticmethod
    def make_greeting(name: str) -> str:
        return "Hello {}!".format(name)


def print_greeting(maker: GreetingMakerBase, name):
    print(maker.make_greeting(name))


print_greeting(HelloGreetingMaker, "John")

Это все еще работает так же, но, очевидно, потому что параметр в вызове функции теперь является именем класса вместо экземпляраоб этом Пичарм жалуется на то, что: Expected type 'GreetingMakerBase', got 'Type[HelloGreetingMaker]' instead.

Есть ли способ, которым я могу решить это предупреждение, не создавая экземпляр класса HelloGreetingMaker?

Ответы [ 2 ]

0 голосов
/ 22 октября 2019

Когда вы делаете print_greeting(HelloGreetingMaker, "John"), вы не пытаетесь передать экземпляр HelloGreetingMaker. Скорее, вы передаете сам класс.

То, как мы его вводим, заключается в использовании Type[T], который указывает, что вы хотите тип T, а не экземпляр T. Так, например:

from typing import Type
import abc

class GreetingMakerBase(abc.ABC):
    @staticmethod
    @abc.abstractmethod
    def make_greeting(name: str) -> str:
        """ Makes greeting string with name of person """


class HelloGreetingMaker(GreetingMakerBase):
    @staticmethod
    def make_greeting(name: str) -> str:
        return "Hello {}!".format(name)


def print_greeting(maker: Type[GreetingMakerBase], name):
    print(maker.make_greeting(name))


# Type checks!
print_greeting(HelloGreetingMaker, "John")

Обратите внимание, что Type[HelloGreetingMaker] считается совместимым с Type[GreetingMakerBase] - Type[T] является ковариантным относительно T.

Документы Python на модуле набора текста и mypy docs содержат больше деталей и примеров, если вы хотите узнать больше.

0 голосов
/ 22 октября 2019

Вы не создали экземпляр, и ваши подсказки типа подразумевают, что функция принимает только экземпляры (что-то типа GreetingMakerBase, а не сам GreetingMakerBase или его подкласс).

ЕслиВы хотите указать, что только GreetingMakerBase сам по себе является приемлемым аргументом, зачем вообще его использовать в качестве аргумента? Просто вызовите функцию внутри этого класса.

В любом случае, в Python 3.8 появилось несколько новых улучшений в типизации, которые могут вам помочь. Вы можете указать буквенную подсказку типа :

from typing import Literal
def print_greeting(maker: Literal[GreetingMakerBase], name):
    print(maker.make_greeting(name))

Если вам нужно поддержать эту подсказку типа в других (ранее 3.8) версиях Python, вам придется установить набирая расширения :

pip install typing-extensions
...