向NumPy数组追加元素时while循环无限运行问题排查
问题描述
需求为接收用户输入的数字序列,计算均值后打印结果,以下是一种基于原生Python列表的实现方案:
user_input = input('Please enter a number type exit to stop:> ') numbers = [] while user_input.lower() != 'exit': while not user_input.isdigit(): print('That is not a number! Numbers only please:> ') user_input = input('Try again:> ') numbers.append(int(user_input)) user_input = input('Please enter next number:> ') total = 0 for number in numbers: total += number print(f'Mean is {total/len(numbers)}') print(sum(numbers)/len(numbers))
现需要对上述代码稍作修改,使用NumPy实现相同逻辑,具体实现思路如下:
- 采集用户输入的数字
- 将数字逐个存储到NumPy中,逐次向NumPy数组追加元素
- 调用
np.ndarray.mean方法计算均值
存在问题的NumPy实现代码
import numpy as np user_nums = np.array([]) user_input = input('Please enter a number type exit to stop:> ') while user_input.lower() != 'exit': while not user_input.isdigit(): print('That is not a number! Numbers only please:> ') user_input = input('Try again:> ') np.append(user_nums,float(user_input)) # append user input to user_nums mean = user_nums.mean() print("mean is ",mean)
问题现象:输入第一个数字后程序就持续运行无响应,只能强制关闭程序。
代码错误说明
代码一共存在2个核心错误,其中第一个就是导致程序卡死无响应的直接原因:
- 外层循环缺少输入更新逻辑,触发死循环
对比原生Python实现可以发现,成功接收一个合法数字、存入存储结构后,原生代码会执行user_input = input('Please enter next number:> ')读取下一次用户输入,让循环判断条件有机会触发退出。但NumPy版本完全漏掉了这行代码,第一次输入合法数字后,user_input变量的值永远是这个数字,永远满足user_input.lower() != 'exit'的循环条件,外层循环会无限空转,程序表现为无响应。 - NumPy数组追加方法使用错误
和Python列表的list.append()原地修改列表的逻辑不同,np.append()不会修改原数组,而是返回元素追加完成后的新数组。现有代码只调用了np.append但没有把返回值重新赋值给user_nums,就算修复了死循环问题,user_nums始终是初始化时的空数组,最后调用均值方法时会得到无效的NaN结果。
修正后代码
import numpy as np user_nums = np.array([]) user_input = input('Please enter a number type exit to stop:> ') while user_input.lower() != 'exit': # 优化校验逻辑,支持识别负数、浮点数 check_input = user_input.replace('.', '', 1).replace('-', '', 1) while not check_input.isdigit(): print('That is not a number! Numbers only please:> ') user_input = input('Try again:> ') check_input = user_input.replace('.', '', 1).replace('-', '', 1) # 追加元素后重新赋值给原数组变量 user_nums = np.append(user_nums, float(user_input)) # 读取下一次输入,避免死循环 user_input = input('Please enter next number:> ') mean = user_nums.mean() print("mean is ", mean)
注:逐次调用
np.append的效率很低,因为NumPy数组每次长度变化都会重新申请整块内存拷贝所有元素,实际使用时更推荐先用Python列表收集所有输入,最后一次性转成NumPy数组计算均值,性能会好很多。
内容的提问来源于stack exchange,提问作者Philosophia
相关产品推荐
相关产品推荐

