跳到内容

non-self-return-type (PYI034)

源自 flake8-pyi 代码检查器。

有时提供修复。

作用

检查使用固定返回类型注释的方法,这些方法应该返回 Self

为什么这不好?

如果在运行时通常返回 self 的方法被注释为固定返回类型,并且该类被子类化,则类型检查器将无法推断出正确的返回类型。

例如

class Shape:
    def set_scale(self, scale: float) -> Shape:
        self.scale = scale
        return self

class Circle(Shape):
    def set_radius(self, radius: float) -> Circle:
        self.radius = radius
        return self

# Type checker infers return type as `Shape`, not `Circle`.
Circle().set_scale(0.5)

# Thus, this expression is invalid, as `Shape` has no attribute `set_radius`.
Circle().set_scale(0.5).set_radius(2.7)

具体来说,此检查强制以下方法的返回类型为 Self

  1. 原地二进制操作的魔术方法,如 __iadd____imul__ 等。
  2. __new____enter____aenter__,如果这些方法返回类名。
  3. 返回 Iterator__iter__ 方法,即使该类直接继承自 Iterator
  4. 返回 AsyncIterator__aiter__ 方法,即使该类直接继承自 AsyncIterator

示例

class Foo:
    def __new__(cls, *args: Any, **kwargs: Any) -> Foo: ...
    def __enter__(self) -> Foo: ...
    async def __aenter__(self) -> Foo: ...
    def __iadd__(self, other: Foo) -> Foo: ...

建议改为

from typing_extensions import Self

class Foo:
    def __new__(cls, *args: Any, **kwargs: Any) -> Self: ...
    def __enter__(self) -> Self: ...
    async def __aenter__(self) -> Self: ...
    def __iadd__(self, other: Foo) -> Self: ...

修复安全性

此规则的修复被标记为不安全,因为它会改变类型注释的含义。

Availability(可用性)

因为此规则依赖于 Python 3.11 之前的第三方 typing_extensions 模块,如果 typing_extensions 导入已被 lint.typing-extensions linter 选项禁用,则不会发出其诊断信息,也不会提供修复。

Options (选项)

参考