gpt4 book ai didi

python - 类型注释 : TypeVar: Bound, 问题

转载 作者:行者123 更新时间:2023-12-03 07:54:36 31 4
gpt4 key购买 nike

在Python中Documentation ,我们发现:

T = TypeVar('T')              # Can be anything
S = TypeVar('S', bound=str) # Can be any subtype of str
A = TypeVar('A', str, bytes) # Must be exactly str or bytes

我们还发现了这段代码:

def repeat(x: T, n: int) -> Sequence[T]:
"""Return a list containing n references to x."""
return [x]*n


def print_capitalized(x: S) -> S:
"""Print x capitalized, and return x."""
print(x.capitalize())
return x


def concatenate(x: A, y: A) -> A:
"""Add two strings or bytes objects together."""
return x + y

然后添加这行代码

print(concatenate("hello ", "world"))

使用 mypy 应该完全没问题,确实如此!

我现在定义一个类:

class sstr(str):
pass

并使用此代码:

s1 = sstr("hello ")
s2 = sstr("world")
print(concatenate(s1, s2))

在 A 的定义中,它说:“必须恰好是 str 或 bytes”s1 和 s2 并不完全是 str 或 bytes,而是 sstr,它是 str 的子类。所以在我看来,mypy 应该引发一个错误,但它说:

Success: no issues found in 1 source file

显然,我一定是出了什么问题。

我什至在类里面尝试过

class sstr(str):
def __add__(self, other):
return self + other + "_42"
def __sub__(self, other):
return "foo"

我做错了什么?有人可以帮忙吗?

最佳答案

“完全”在这里具有误导性。一般来说,类型系统假定里氏可替换性。因此,T 类型的子类型 S 始终可以代替 T。 “确切”是指特定的行为。当您使用受约束而不是绑定(bind)类型变量*时,结果始终是 strbytes,因此即使您提供 MyStr,就类型检查器而言,它返回一个 str:

import typing

T = typing.TypeVar("T", str, bytes)

class MyString(str):
pass


def alphabetize(a: T, b: T) -> T:
if a >= b:
return a
else:
return b


c0 = alphabetize("foo", "bar")
c1 = alphabetize("foo", MyString("bar"))
c2 = alphabetize(MyString("foo"), MyString("bar"))

reveal_type(c0)
reveal_type(c1)
reveal_type(c2)

使用mypy给出:

test_typing.py:20: note: Revealed type is "builtins.str"
test_typing.py:21: note: Revealed type is "builtins.str"
test_typing.py:22: note: Revealed type is "builtins.str"
Success: no issues found in 1 source file

PEP 483 中是这样描述的,第一个描述类型系统如何工作以及类型变量的概念的 PEP:

A constrained type variable ranges only over constrains t1, etc.exactly; subclasses of the constrains are replaced by the most-derivedbase class among t1,

但是,当您给它一个上限时,它就不是这样工作的:

import typing

T = typing.TypeVar("T", bound=str)

class MyString(str):
pass


def alphabetize(a: T, b: T) -> T:
if a >= b:
return a
else:
return b


c0 = alphabetize("foo", "bar")
c1 = alphabetize("foo", MyString("bar"))
c2 = alphabetize(MyString("foo"), MyString("bar"))

reveal_type(c0)
reveal_type(c1)
reveal_type(c2)

mypy 为您提供:

test_typing.py:20: note: Revealed type is "builtins.str"
test_typing.py:21: note: Revealed type is "builtins.str"
test_typing.py:22: note: Revealed type is "test_typing.MyString"
Success: no issues found in 1 source file

请注意,在混合类型的情况下,结果是可能的最窄的常见类型。考虑一种具有更深继承层次结构的情况:

import typing

T = typing.TypeVar("T", bound=str)

class SpecialString(str):
pass

class SuperSpecialString(SpecialString):
pass

def alphabetize(a: T, b: T) -> T:
if a >= b:
return a
else:
return b


c0 = alphabetize(SpecialString("foo"), SuperSpecialString("bar"))
c1 = alphabetize("foo", SuperSpecialString("bar"))
c2 = alphabetize(SuperSpecialString("foo"), SuperSpecialString("bar"))

reveal_type(c0)
reveal_type(c1)
reveal_type(c2)

在这里,mypy 给出:

test_typing.py:22: note: Revealed type is "test_typing.SpecialString"
test_typing.py:23: note: Revealed type is "builtins.str"
test_typing.py:24: note: Revealed type is "test_typing.SuperSpecialString

关于python - 类型注释 : TypeVar: Bound, 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76346099/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com