这个Python的逻辑表达式能被NumPy表达式替代吗?
在这个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 <= 5 与 N, 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导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。