为什么Pycharm在处理可能返回多个输出的Scipy函数时会遇到困难?

-1 投票
1 回答
31 浏览
提问于 2025-04-14 15:19

Scipy是Python中最常用的科学计算库之一。它的大部分功能都有一个共同的特点:要么返回一个值(这个值可以是float或者np.ndarray),要么返回一个tuple,其中第二个元素是boolean或者dict。大概就是这样的:

value = some_scipy_function(*args, full_output=False)
value, flag = some_scipy_function(*args, full_output=True)

不过,如果你在使用PyCharm的时候,它总是会对SciPy的函数发出警告,因为它不明白当full_output设置为False时,这些函数其实只会返回一个值。


那么,为什么PyCharm这么难做到这一点呢?这些信息不仅在SciPy函数的文档字符串中可以找到,而且从代码中也能明显看出来,在执行之前就能知道。此外,它通常不允许你关闭这些警告,可能是因为这些警告被视为重大警告(比如从一个元组中减去东西是不可能的)。

虽然有点沮丧,但我觉得这有点奇怪:如果你使用Python最常用的科学计算库,你的文件却因为这个原因充满了无法关闭的警告。我难道是唯一一个对此感到沮丧的人吗?


示例

  • logsumexp(或者一般来说,大多数线性代数函数)
  • brentq(或者一般来说,大多数优化函数)
from scipy.special import logsumexp

logw = np.log(np.random.rand(1000))
lse_plus_value = 1.0 + exp(logsumexp(logw, return_sign=False))  # raises a warning

1 个回答

1
from scipy.special import logsumexp

a, b = logsumexp([1, 2, 3, 4], b=[4, 3, 2, 1], return_sign=True)

因为PyCharm无法推断返回类型是变量类型,原因是SciPy没有提供类型提示文件(而且PyCharm内部也没有这些文件),这些文件会定义像logsumexp这样的函数的重载信息,这些信息仅通过文档字符串来说明。

返回值

res : ndarray
结果是通过更稳定的数值计算方式得到的,计算公式是np.log(np.sum(np.exp(a)))。如果给定了b,那么返回的结果是np.log(np.sum(b*np.exp(a)))

sgn : ndarray
如果return_sign为True,这将是一个与res匹配的浮点数数组,值为+1、0或-1,取决于结果的符号。如果为False,则只返回一个结果。

添加这种类型注释的机制可以使用@typing.overload,类似于下面的内容:

@overload
def logsumexp(..., return_sign=True) -> tuple[ndarray, bool]:

@overload
def logsumexp(..., return_sign=False) -> ndarray:

顺便说一下,我在我的PyCharm 2023.3.4(专业版)中没有看到“无法抑制的警告”。
当然,你可以通过在这样的代码行后添加类型注释来让PyCharm更好地理解,例如:

b: bool

或者甚至使用typing.cast

a, b = cast(tuple[ndarray, bool], logsumexp(...))

撰写回答