You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python使用sorted()后触发AttributeError问题及修复方法咨询

问题分析与修复方案

你猜的没错!问题确实出在sorted()返回的类型上——data.items()是字典的键值对视图,用sorted()处理后会变成一个列表,里面的每个元素是(batch, sample)这样的元组,而列表根本没有.items()方法,这就是你看到AttributeError: 'list' object has no attribute 'items'的原因。

核心修复步骤

1. 修改average函数的循环逻辑

因为sorted_data是列表(每个元素是(批次名, 对应样本列表)的元组),直接遍历这个列表即可,不需要调用.items():

def average(sorted_data):
    # 把原来的 sorted_data.items() 改成直接遍历 sorted_data
    for batch, sample in sorted_data:
        if len(sample) > 0:
            n = 0
            x_sum = 0
            for (x, y, val) in sample:
                if x**2 + y**2 <= 1:
                    x_sum += val
                    n += 1
            try:
                average_val = x_sum/n  # 这里变量名不要用average,和函数名重名会有问题
            except ZeroDivisionError: # utanför enhetscirkeln
                print("Other measurements are made outside the unit circle")
                continue
            zero_data = False
        else:
            zero_data = True
        print_average(batch, average_val, zero_data)

另外注意:我把变量名average改成了average_val,避免和函数名average重名导致的潜在问题。

2. 清理collect_data函数的冗余代码

你的collect_data函数里有两个return语句,第一个return data会直接终止函数,后面的return sorted_data永远不会执行。如果不需要这个函数返回排序后的列表,可以删掉相关代码;如果需要,可以调整成只返回排序后的列表:

def collect_data(filename):
    data = dict()
    with open(filename, 'r') as h:
        for line in h:
            four_vals = line.split(',')
            batch = four_vals[0]
            if not batch in data:
                data[batch] = []
            try:
                data[batch] += [(float(four_vals[1]), float(four_vals[2]), float(four_vals[3]))]
            except ValueError:
                print("String not a float")
    # 删掉冗余的return,只返回排序后的列表(或者根据需求返回原始字典)
    sorted_data = sorted(data.items(), key=operator.itemgetter(0))
    return sorted_data

如果做了这个修改,main函数里就可以简化成:

def main():
    ''' This is the main body of the program. '''
    filename = input('Which data file? ')
    sorted_data = collect_data(filename)
    average(sorted_data)

额外优化建议:按数字而非字符串排序你的批次

目前你的batch是字符串类型(比如"3"、"1"),用sorted(data.items(), key=operator.itemgetter(0))是按字符串排序的。如果后续批次号超过9(比如"10"),字符串排序会把"10"排在"2"前面,不符合数字逻辑。

可以把批次号转换成整数来解决:

def collect_data(filename):
    data = dict()
    with open(filename, 'r') as h:
        for line in h:
            four_vals = line.split(',')
            # 把batch转换成整数,处理可能的空格
            batch = int(four_vals[0].strip())
            if not batch in data:
                data[batch] = []
            try:
                # 同样去掉坐标值的空格,避免转换float出错
                x = float(four_vals[1].strip())
                y = float(four_vals[2].strip())
                val = float(four_vals[3].strip())
                data[batch].append((x, y, val))  # 用append比+=更直观
            except ValueError:
                print(f"Invalid number in line: {line.strip()}")
    # 按数字排序批次
    sorted_data = sorted(data.items(), key=operator.itemgetter(0))
    return sorted_data

完整修复后的代码

import operator

def collect_data(filename):
    data = dict()
    with open(filename, 'r') as h:
        for line in h:
            four_vals = line.split(',')
            # 转换批次为整数,处理可能的空格
            batch = int(four_vals[0].strip())
            if batch not in data:
                data[batch] = []
            try:
                x = float(four_vals[1].strip())
                y = float(four_vals[2].strip())
                val = float(four_vals[3].strip())
                data[batch].append((x, y, val))
            except ValueError:
                print(f"Warning: Could not parse line '{line.strip()}' - skipping.")
    # 返回按批次数字排序后的列表
    return sorted(data.items(), key=operator.itemgetter(0))

def average(sorted_data):
    for batch, sample in sorted_data:
        zero_data = len(sample) == 0
        average_val = None
        if not zero_data:
            n = 0
            x_sum = 0
            for (x, y, val) in sample:
                if x**2 + y**2 <= 1:
                    x_sum += val
                    n += 1
            try:
                average_val = x_sum / n
            except ZeroDivisionError:
                print(f"Batch {batch}: All measurements are outside the unit circle")
                continue
        print_average(batch, average_val, zero_data)

def print_average(batch, average_val, zero_data):
    if zero_data:
        print(f"{batch}\tNo data")
    else:
        print(f"{batch}\t{average_val:.4f}")  # 格式化输出更美观

def main():
    ''' This is the main body of the program. '''
    filename = input('Which data file? ')
    sorted_data = collect_data(filename)
    average(sorted_data)

# Start the main program: This is idiomatic python
if __name__ == '__main__':
    main()

内容的提问来源于stack exchange,提问作者idlatva

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 07:28:26