这个Python的逻辑表达式能被NumPy表达式替代吗?

编程语言 2026-07-10

在这个Python片段中:

import numpy as np

N, M, K = 9, 10, 2
a = np.random.randint(2*K, size=(N, M)) 
r = np.any(a[0, :]==K) and np.any(a[-1, :]==K) and np.any(a[:, 0]==K) and np.any(a[:, -1]==K)

最后一行中的 and 运算符能被NumPy的运算符/函数所替代吗?原因是为了提升效率并出于好奇。


我的使用场景是 K <= 5N, M < 32。当然不是追求极致性能,而是避免明显的性能损失。

解决方案

你可以在这里使用多种方法:

  • & 适用于标量。
  • np.logical_and.reduce()
  • np.all()一个列表 []

下面给出按时间对比上述方法的代码:

# Source - https://stackoverflow.com/a/79919211
# Posted by Mohammad Othman
# Retrieved 2026-04-02, License - CC BY-SA 4.0

import numpy as np
import time


N, M, K = 10000, 10000, 1000000
a = np.random.randint(2 * K, size=(N, M))
element = 9999


def method_and():
    return (
        np.any(a[0, :] == element)
        and np.any(a[-1, :] == element)
        and np.any(a[:, 0] == element)
        and np.any(a[:, -1] == element)
    )


def method_bitwise():
    return (
        np.any(a[0, :] == element)
        & np.any(a[-1, :] == element)
        & np.any(a[:, 0] == element)
        & np.any(a[:, -1] == element)
    )


def method_logical_reduce():
    return np.logical_and.reduce(
        [
            np.any(a[0, :] == element),
            np.any(a[-1, :] == element),
            np.any(a[:, 0] == element),
            np.any(a[:, -1] == element),
        ]
    )


def method_np_all():
    return np.all(
        [
            np.any(a[0, :] == element),
            np.any(a[-1, :] == element),
            np.any(a[:, 0] == element),
            np.any(a[:, -1] == element),
        ]
    )


iterations = 10000
methods = [
    ('Python "and"', method_and),
    ('Bitwise "&"', method_bitwise),
    ("np.logical_and.reduce()", method_logical_reduce),
    ("np.all() with list", method_np_all),
]
for name, func in methods:
    start = time.perf_counter()
    for _ in range(iterations):
        result = func()
    elapsed = time.perf_counter() - start
    print(f"{name:<25} | {elapsed:.4f} sec | Result: {result}")

在我的电脑上运行这段代码的结果是:

Python "and"              | 0.0734 sec | Result: False
Bitwise "&"               | 1.9812 sec | Result: False
np.logical_and.reduce()   | 1.9811 sec | Result: False
np.all() with list        | 2.0431 sec | Result: False

因此 and 具备最短的执行时间,因为具备 Short-circuiting.

备选方案

我认为你不能把所有的 ands全部替换成NumPy运算,但可以替换其中的两个:

(a[::N-1, :] == K).any(axis=1).all() and (a[:, ::M-1] == K).any(axis=0).all()

对于给定的数组大小,直接对整个数组计算 a==K 也更快:

k = a == K
k[::N-1, :].any(axis=1).all() and k[:, ::M-1].any(axis=0).all()

时间统计如下:原问题中的原始实现耗时8.7微秒,第一个实现耗时6.2微秒,第二个实现耗时4.8微秒,针对 M, N, K = 31, 31, 5

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章