Python 静态协议 VS Pyright 消息

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

我正在尝试了解 Python 中的泛型是如何工作的。

我从 Fluent Python 书中得到了一个例子。它工作正常,但我想知道是否可以让pyright checker满意?

from typing import Protocol


class Repeatable[T](Protocol):
    def __mul__(self: T, repeat_count: int) -> T: 
        ...
        

def double[RT: Repeatable](x: RT) -> RT:
    return x * 2


if __name__ == '__main__':
    print(double(3))  # pyright error
    print(double('A'))  # pyright error
    print(double([1, 2]))  # pyright error

感谢您的帮助!

python generics protocols pyright
1个回答
0
投票

有两个问题:

  1. 类型参数
    T
    用作自类型,但绑定到类型实例本身。这是逻辑上的矛盾;
    T
    不能随.r.t. 变化。
    Repeatable
    的实例,因为它静态地绑定到该实例。相反,您可以使用
    typing.Self
    ,或将
    T
    移动到
    __mul__
    范围。
  2. __mul__
    的参数有一个特定的名称,可以用作位置参数或关键字参数。因此,因为它可以用作关键字 arg,所以名称很重要,即
    obj.__mul__(repeat_count=...)
    obj.__mul__(birds_arent_real=...)
    不同。同样,这里有两种可能的解决方案;使其仅具有位置性(即在其后面放置
    /
    ),或“删除”名称(即在其前面添加
    __
    )。

为了说明这一点,这是可能的解决方案之一

from typing import Protocol, Self


class Repeatable(Protocol):
    def __mul__(self, elmo_did_nothing_wrong: int, /) -> Self: 
        ...
        

def double[RT: Repeatable](x: RT) -> RT:
    return x * 2


if __name__ == '__main__':
    print(double(3))  # all good
    print(double('A'))  # still good
    print(double([1, 2]))  # don't eat the yellow snow, son.

pyright 游乐场 亲眼看看。它甚至可以在 Pyright 严格模式下工作(在期望模式下,它在快速奔跑彩虹路时“穿越火与火焰”获得 5 颗星)。

© www.soinside.com 2019 - 2024. All rights reserved.