使用列表推导式筛选列表元素时触发ValueError问题咨询
错误原因
报错的核心是你遍历dist_vals时取到的元素不是单个距离值,而是一维numpy数组,和纯Python测试用例的一维标量列表结构完全不同:
- 你生成
dist_vals用了双层列表推导,外层遍历第一组50个点,内层遍历第二组50个点,最终dist_vals是50×50的二维结构——也就是说for x in dist_vals取到的每个x,是包含50个距离值的整行数组,不是单个浮点数。 - 当你对numpy数组写
x>r时,返回的是和x同长度的布尔数组,每个元素对应位置的比较结果。Python原生的and运算符只能判断单个布尔值的真假,没法直接判定多元素布尔数组是真还是假,就会抛出你看到的ValueError: The truth value of an array with more than one element is ambiguous。 - 你的纯Python测试用例里
a是一维标量列表,遍历得到的每个x都是单个整数,比较后返回单个布尔值,自然不会触发这个错误。
额外提一句:numpy.random.default_rng是NumPy 1.17版本才新增的API,Python 3.6.9默认搭配的NumPy版本普遍低于1.17,直接跑你写的随机数生成代码也会报导入/属性错误,要在3.6环境运行需要换成旧版np.random.choice的写法。
修复方案
最小改动版
不需要改原有距离计算逻辑,只要把二维的dist_vals展平成一维标量列表,再做计数即可:
# 展平二维距离列表,每个元素都是单个距离值 dist_vals_flat = [single_dist for row in dist_vals for single_dist in row] counts = [sum(r < x <= r + drval for x in dist_vals_flat) for r in rvals]
向量化提速版(推荐)
你本来的目的是降低运行耗时,用NumPy就没必要在Python层写双层循环算距离、循环计数,全部改成数组向量化操作,运行速度会比列表推导快几十倍:
import numpy as np # Python3.6兼容的随机数生成写法(替换default_rng相关代码) np.random.seed(42) # 可去掉,固定随机种子仅用于结果复现 xpos1 = np.random.choice(1000, size=50, replace=False)/100 ypos1 = np.random.choice(1000, size=50, replace=False)/100 xpos2 = np.random.choice(1000, size=50, replace=False)/100 ypos2 = np.random.choice(1000, size=50, replace=False)/100 # 一次性计算所有点对的坐标差,对应原dist函数的周期性边界距离逻辑 dx = xpos1[:, None] - xpos2[None, :] dy = ypos1[:, None] - ypos2[None, :] dx = dx - 10 * np.floor(dx / 10 + 0.5) dy = dy - 10 * np.floor(dy / 10 + 0.5) all_dists = np.sqrt(dx**2 + dy**2).flatten() # 直接得到一维的全部距离值数组 # 用直方图批量统计每个壳层的点数,替代循环sum bin_edges = np.concatenate([np.array(rvals), [rvals[-1] + drval]]) counts, _ = np.histogram(all_dists, bins=bin_edges)
内容的提问来源于stack exchange,提问作者mal.phys.v
相关产品推荐
相关产品推荐

