TypeVar中__name__的作用是什么?NewType又是什么?

11
typing 模块中,TypeVarNewType 都需要一个字符串作为第一个位置参数,该字符串将用作所创建对象的 __name__ 属性。那么这里的 __name__ 的目的是什么呢?
考虑到这是一个必选参数,我希望它是至关重要的东西。在 PEP-484 中引入类型提示时,通常将该参数设置为分配给对象的变量名的字符串:
T = TypeVar('T', int, float, complex)

但是,我无法真正确定这个在 CPython 中如何被用于 typing.py。在我的测试中,用任何其他字符串替换该字符串似乎不会导致任何问题。


1
它相当于一个正常类的类名,例如 class T: pass 中的 T。声明 TypeVar 不会在运行时设置类名,因此我们通过给予 nametag 来访问 TypeVar 的确切名称来帮助自己。但是,正如您正确注意到的那样,没有任何强制要求我们这样做。这是否解决了问题,或者您的问题有不同的意思? - Arne
嗨,阿恩!您是否熟悉以某种方式设置名称属性的任何用例? 我感觉__name__在模块级别上大多有用,在那里我们进行导入和普遍使用的if __name__ == "__main__": pass。 对于类名,我将不得不在调用或实例化类时使用它,但对于TypeVarNewType,这是通过已分配的变量名称完成的,因此在类型函数的上下文中,该属性如何使用? - Melvin
1个回答

10

__name__属性是关联的类型名称,例如,IDE将在其类型提示中使用该名称。给定以下示例代码:

T = TypeVar('not_T', int, float)
def test_func(arg: T): pass

如果使用类似于test_func('not_a_number')这样不正确的参数调用函数,会得到如下类型提示:

Expected type 'not_t', got 'str' instead

就Python解释器而言,它并没有对type.__name__和你用来处理它的名称标签之间的一致性设置限制,但是其他第三方工具(比如mypy)可能不接受变量名和__name__不同的情况。这在初始类型PEP-484中也是一个要求:

TypeVar()的参数必须是与其分配到的变量名相等的字符串。类型变量不能被重新定义。


对于额外的用例,您还可以检查任何对象的__annotations__成员中的类型,以便进行类型提示,例如:
print(test_func.__annotations__)
>> {'arg': ~not_T}

使用它来在您的代码中实现进一步的类型检查或处理-在这种情况下,您的TypeVar.__name__最好具有意义 :)


这真的很有用,它解决了我对如何使用类型提示的许多疑惑。非常感谢! - Melvin
这个回答有一些误导性:对于 TypeVar,字符串参数必须与变量名相同,例如请参见 PEP。 这也被 mypy 和 pyright 强制执行。(NewType 没有这种记录要求。但是它被 mypy 所强制执行。Pyright 目前不强制执行。) - Carl
@Carl 谢谢你指出这一点,我已经在帖子中加入了它。 - Arne

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接