Pycharm 类型提示针对类而不是实例发出警告

问题描述 投票:0回答:2

我试图理解为什么 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")

这仍然以相同的方式工作,但显然因为函数调用中的参数现在是类名而不是它的实例,Pycharm 抱怨:

Expected type 'GreetingMakerBase', got 'Type[HelloGreetingMaker]' instead.

有没有办法可以解决此警告,而无需实例化

HelloGreetingMaker
类?

python pycharm python-typing
2个回答
4
投票

当您执行

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 文档 有更多详细信息和示例。


0
投票

您没有创建实例,并且您的类型提示意味着该函数仅接受实例(

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
© www.soinside.com 2019 - 2024. All rights reserved.