【问题标题】:Type checking returned class PEP 484类型检查返回类 PEP 484
【发布时间】:2016-08-03 14:48:44
【问题描述】:

我在 python 中有一个函数,它返回一个类而不是一个实例。如何指示返回值是特定类型的子类?

在下面的示例中,我将返回值设置为类型,但我想进一步指出该类型具有 BaseClass 的所有属性:

from typing import Dict, Any

def class_constructor(name: str, attrs: Dict[str, Any]) -> type
    ConstructedClass = type(name, (BaseClass,), attrs)
    return ConstructedClass

class BaseClass: ...

我不能说 (...) -> BaseClass,因为那将指示 BaseClass 的实例而不是 BaseClass 本身。

为了回答我自己的问题,这显示为python/typing issue #107。目前,最好的解决方案是:

from typing import Dict, Any

class BaseClass: ...

def class_constructor(name: str, attrs: Dict[str, Any]) -> Callable[Any, BaseClass]
    ConstructedClass = type(name, (BaseClass,), attrs)
    return ConstructedClass

如果您知道自己的__init__ 签名,则可以在Callable[Any, ...] 中使用它来代替Any

添加对Type[T] 的支持后,解决方案将是:

 from typing import Dict, Any

class BaseClass: ...

def class_constructor(name: str, attrs: Dict[str, Any]) -> Type[BaseClass]
    ConstructedClass = type(name, (BaseClass,), attrs)
    return ConstructedClass

【问题讨论】:

  • 您能否提供一个具体的、可运行的示例,但该示例无法满足您的要求?
  • 在 mypy 和 PEP 484 中都添加了对 Type[T] 的支持。

标签: python typing type-hinting


【解决方案1】:

我认为您需要创建一个新类,BaseClass 仅将其用作标记它和任何后代类的一种方式。

 class BaseClassMeta(type):
     pass

 class BaseClass(metaclass=BaseClassMeta):
     ...

 def class_constructor(name: str, attrs: Dict[str, Any]) -> BaseClassMeta
     ConstructedClass = BaseClassMeta(name, (BaseClass,), attrs)
     return ConstructedClass

【讨论】:

  • 生成的类确实可以正常运行,但不能解决问题。 BaseClassMeta(...) 产生一个类型,而ConstructedClass(...) 产生一个对象,所以返回的类型不能是BaseClassMeta。我可以使用-> Callable[[...], BaseClass] 更接近我需要的东西,其中...__init__ 函数的参数(它必须为所有构造的类共享一个公共接口才能使这段代码完全合理)。如果不是返回类的属性,至少 PyCharm 能够推断出 ConstructedClass(...) 对象的属性。
  • 为什么不呢?您实际上在哪里创建ConstructedClass 的实例? BaseClassConstructedClass 都是 BaseClassMeta 的实例。
  • 类构造函数的返回值确实是BaseClassMeta的一个实例,但它的行为不同。也就是说,BaseClassMeta(...) -> typeConstructedClass(...) -> object。如果您说class_constructor 返回BaseClassMeta,那么当您稍后说obj = MyClass() 时,使用MyClass = class_constructor(...) 的静态分析将失败,因为BaseClassMeta 类型的MyClass 期待与type 相同的签名功能。
  • 你没有在class_constructor 中实例化ConstructedClass,所以我看不出ConstructClass(...) 返回object 类型的东西有什么关系。 class_constructor 并没有说明 MyClass.__call__ 返回的内容。
  • BaseClassMeta 的返回类型表示承诺返回值具有BaseClassMeta 的属性,包括其__call__ 方法的行为。就像List[str] 的返回类型会保证返回值的__getitem__ 方法将具有签名(int) -> str 或重载(Slice) -> List[str]
猜你喜欢
  • 1970-01-01
  • 2018-11-05
  • 2018-03-01
  • 2016-10-26
  • 2019-03-21
  • 2019-10-07
  • 2023-03-31
  • 1970-01-01
相关资源
最近更新 更多