如何在Python中输入提示泛型数值类型?

goucqfw6  于 2023-02-26  发布在  Python
关注(0)|答案(3)|浏览(129)

请原谅,这个问题以前有人问过,但我找不到任何相关的答案。
考虑一个将数值类型作为输入参数的函数:

def foo(a):
    return ((a+1)*2)**4;

这适用于整数、浮点数和复数。
是否有一个基本类型,以便我可以做类型提示(真实的存在的类型/基类),例如:

def foo(a: numeric):
    return ((a+1)*2)**4;

此外,我需要在集合类型参数中使用它,例如:

from typing import Collection;
def foo(_in: Collection[numeric]):
    return ((_in[0]+_in[1])*2)**4;
yeotifhr

yeotifhr1#

PEP 3141为数字添加了抽象基类,因此您可以用途:

from numbers import Number

def foo(a: Number) -> Number:
    ...
uhry853o

uhry853o2#

typing模块中没有泛型数值类型,所以你必须用Union创建这样一个类型:

from typing import Union

numeric = Union[int, float, complex]

...

要添加对Numpy的数字类型集合的支持,请将np.number添加到该Union。

numeric = Union[int, float, complex, np.number]
kb5ga3dv

kb5ga3dv3#

目前公认的使用Number的解决方案是相当不合理的,正如评论中指出的,对于静态类型检查器(如mypy和PyRight),int不是Number
detailed explanation from a related question中提取的另一种可能的方法是:

from typing import SupportsFloat as Numeric

其具有以下行为:

from decimal import Decimal
from fractions import Fraction
from typing import SupportsFloat as Numeric

import numpy as np

def f(x: Numeric) -> None:
    pass

# Accepted by mypy/Pyright:
f(123)
f(np.uintc(55))
f(Fraction(-3, 2))
f(Decimal("-3.14"))
f(np.array([1, 2, 3]))  # Should an array be numeric?

# Results in type errors:
f(complex(2, 3))
f("asdf")

这样做的好处是相当宽松,除了complex。如果您还想包括complex,只需这样做

from typing import SupportsFloat, Union

Numeric = Union[SupportsFloat, complex]

或等同于Python ≥3.10风格:

from typing import SupportsFloat, TypeAlias

Numeric: TypeAlias = SupportsFloat | complex

NumPy数组在SupportsFloat的意义上被认为是数字,这也许是不幸的,但这说明了“什么是数字"这个问题的晦涩的哲学本质。

主要缺点:

正如@lkwbr所指出的,SupportsFloat类型实际上只适合于识别数字,它不支持加法或比较之类的运算符。
例如,Pyright给出以下错误:
类型“SupportsFloat”和“SupportsFloat”不支持运算符“〈”

相关问题