跳到内容

generic-not-last-base-class (PYI059)

源自 flake8-pyi 代码检查器。

有时提供修复。

此规则不稳定且处于预览状态。使用需要 --preview 标志。

作用

检查继承自 typing.Generic[] 的类,其中 Generic[] 不是基类元组中的最后一个基类。

为什么这不好?

如果 Generic[] 不是基类元组中的最后一个类,则在运行时可能会发生意外行为(有关示例,请参阅 这个 CPython 问题)。

该规则也适用于存根文件,虽然在运行时不会导致问题。 这是因为类型检查器可能无法推断出准确的类的 MRO (方法解析顺序),这可能会在他们分析你的代码时导致意外或不准确的结果。

例如

from collections.abc import Container, Iterable, Sized
from typing import Generic, TypeVar


T = TypeVar("T")
K = TypeVar("K")
V = TypeVar("V")


class LinkedList(Generic[T], Sized):
    def push(self, item: T) -> None:
        self._items.append(item)


class MyMapping(
    Generic[K, V],
    Iterable[tuple[K, V]],
    Container[tuple[K, V]],
):
    ...

建议改为

from collections.abc import Container, Iterable, Sized
from typing import Generic, TypeVar


T = TypeVar("T")
K = TypeVar("K")
V = TypeVar("V")


class LinkedList(Sized, Generic[T]):
    def push(self, item: T) -> None:
        self._items.append(item)


class MyMapping(
    Iterable[tuple[K, V]],
    Container[tuple[K, V]],
    Generic[K, V],
):
    ...

修复安全性

此规则的修复总是不安全的,因为重新排序基类可以通过修改类的 MRO 来改变代码的行为。 如果存在多行基类列表,该修复还会删除 Generic 基类之后的尾随注释。

修复可用性

只有当基类列表中没有 *args 时,此规则的修复才可用。

参考