numpy.apply_along_axis 上的 mypy 警告

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

编辑2024年10月18日:

下面显示了该问题的更简单的重现。

mypy_arg_type.py

import numpy as np
from numpy.typing import NDArray
import random

def winner(_: NDArray[np.bytes_]) -> bytes | None:
    return b"." if bool(random.randint(0, 1)) else None

board = np.full((2, 2), ".", "|S1")
for w in np.apply_along_axis(winner, 0, board):
    print(w)

>> python mypy_arg_type.py

b'.'
None

>> mypy mypy_arg_type.py

mypy_arg_type.py:9: error: Argument 1 to "apply_along_axis" has incompatible type "Callable[[ndarray[Any, dtype[bytes_]]], bytes | None]"; expected "Callable[[ndarray[Any, dtype[Any]]], _SupportsArray[dtype[Never]] | _NestedSequence[_SupportsArray[dtype[Never]]]]"  [arg-type]
mypy_arg_type.py:9: note: This is likely because "winner" has named arguments: "_". Consider marking them positional-only
Found 1 error in 1 file (checked 1 source file)

原问题:

我正在解决一个问题,根据棋盘上棋子的位置确定“四连子”游戏的获胜者。 棋盘尺寸为 6x7,每列都标有从 A

G
的字母。获胜者(如果有的话)将拥有 4 颗相同颜色的棋子,排列成行、列、对角线或反对角线。
示例:

输入:

["A_Red", "B_Yellow", "A_Red", "B_Yellow", "A_Red", "B_Yellow", "G_Red", "B_Yellow"]

董事会:

R Y . . . . R R Y . . . . . R Y . . . . . . Y . . . . . . . . . . . . . . . . . . .

获胜者:
Yellow

以下代码决定获胜者。

import itertools import numpy as np from numpy.typing import NDArray def who_is_winner(pieces: list[str]) -> str: def parse_board() -> NDArray[np.bytes_]: m, n = 6, 7 indices = [0] * n # https://numpy.org/doc/stable/user/basics.strings.html#fixed-width-data-types # One-byte encoding, the byteorder is ‘|’ (not applicable) board = np.full((m, n), ".", "|S1") for p in pieces: col = ord(p[0]) - ord("A") board[indices[col], col] = p[2] indices[col] += 1 return board def winner(arr: NDArray[np.bytes_]) -> np.bytes_ | None: i = len(arr) xs = next( (xs for j in range(i - 3) if (xs := set(arr[j : j + 4])) < {b"R", b"Y"}), {None}, ) return xs.pop() def axis(x: int) -> np.bytes_ | None: # https://numpy.org/doc/2.0/reference/generated/numpy.apply_along_axis.html#numpy-apply-along-axis # Axis 0 is column-wise, 1 is row-wise. return next( (w for w in np.apply_along_axis(winner, x, board) if w is not None), None ) def diag(d: int) -> np.bytes_ | None: # https://numpy.org/doc/stable/reference/generated/numpy.diagonal.html#numpy-diagonal # Diagonal number is w.r.t. the main diagonal. b = board if bool(d) else np.fliplr(board) return next( (w for d in range(-3, 4) if (w := winner(b.diagonal(d))) is not None), None ) board = parse_board() match next( ( w for f, i in itertools.product((axis, diag), (0, 1)) if (w := f(i)) is not None ), None, ): case b"Y": return "Yellow" case b"R": return "Red" case _: return "Draw"

但是,这会产生 mypy 违规,如下所示:

error: Argument 1 to "apply_along_axis" has incompatible type "Callable[[ndarray[Any, dtype[bytes_]]], bytes_ | None]"; expected "Callable[[ndarray[Any, dtype[Any]]], _SupportsArray[dtype[bytes_]] | _NestedSequence[_SupportsArray[dtype[bytes_]]]]" [arg-type] note: This is likely because "winner" has named arguments: "arr". Consider marking them positional-only

根据
apply_along_axis

的文档,它应该返回单个值,这与上面的代码一致。 如何解决此违规问题?使函数

winner

仅定位没有什么区别,只是建议消失了。

我正在使用 Python 3.12.5 和 mypy 1.11.2。

python numpy python-typing mypy
1个回答
0
投票

例如:

import numpy as np from typing import Any def custom_function(arr: np.ndarray) -> Any: # Your function logic return np.sum(arr)

使用 # type:ignore 来处理导致警告的行:如果您无法消除警告,并且您确信代码按预期工作,则可以通过添加 #type:ignore 来告诉 Mypy 忽略它到那条线。它不适合长期使用,但可以快速修复:

result = np.apply_along_axis(custom_function, axis=0, arr=my_array) # type: ignore

考虑 NumPy 的 Mypy 插件:为了提高 Mypy 对 NumPy 等库的理解做了很多努力。您可能想研究提供更好支持的第三方插件或输入存根,尽管它们仍在进行中。

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