Python类初始化异常求助:子类实例属性c全部返回'0'
嘿,我来帮你找出所有实例c属性都返回'0'的原因,咱们一步步拆解修复:
1. 核心问题:误用类属性而非实例属性
你在A和B的构造函数里,用了B.c = c这种类属性赋值,而不是self.c = c的实例属性。类属性是所有实例共享的“全局变量”——每创建一个新的B实例,就会覆盖这个类属性的值。如果最后一个实例触发了else分支把B.c设为'0',那之前所有实例的c都会跟着变成'0',因为它们共享同一个属性。
举个直观的例子:
b1 = B("test1", "hello") b2 = B("test2", "") # 这个实例会把类属性B.c改成'0' print(b1.c) # 结果是'0',因为b1共享的类属性被b2覆盖了
修复方法:把所有类属性的赋值改成实例属性,用self代替类名,同时别忘了调用父类的构造函数(否则A的a属性不会被初始化):
class A: def __init__(self, a): self.a = a # 每个实例拥有独立的a属性 class B(A): def __init__(self, b, c): super().__init__(b) # 必须调用父类构造函数,初始化A的属性 self.b = b # 每个实例拥有独立的b属性 if c: self.c = c # 每个实例拥有独立的c属性 else: self.c = '0'
2. 构造函数参数不匹配,错误被静默忽略
你在get_list里调用B(row[0], row[1], row[2]),传了三个参数,但B的构造函数只定义了b和c两个参数(加上self一共三个参数),这必然会抛出TypeError。但你用了try-except: pass把错误直接吞掉了,导致你根本没发现这个问题。
如果你的CSV每行确实有三列,想把第一列传给A的a,那得修改B的构造函数,让它接收三个参数:
class B(A): def __init__(self, a, b, c): super().__init__(a) # 把a传给父类A的构造函数 self.b = b if c: self.c = c else: self.c = '0'
另外,千万别用except: pass这种宽泛的异常捕获,它会隐藏所有潜在错误,建议改成捕获特定异常或者打印错误信息:
def get_list(csv_filename): test_list = [] import csv # 你之前的代码没导入csv模块,这也是个隐藏问题! with open(csv_filename) as csv_file: reader = csv.reader(csv_file, delimiter=';') next(reader) try: for row in reader: if len(row) >= 3: # 先判断行是否完整,避免索引越界 test_list.append(B(row[0], row[1], row[2])) else: print(f"跳过不完整的行: {row}") except Exception as e: print(f"读取CSV出错了: {str(e)}") return test_list
3. CSV中的"None"值不是Python的None
你提到CSV里有部分None值,但csv.reader读出来的是字符串'None',不是Python的None对象。所以if c:判断时,'None'是个非空字符串,会被当成True,不会走到else分支设为'0'。如果你的CSV用'None'表示空值,得显式判断:
if c and c.strip() != 'None': self.c = c else: self.c = '0'
4. 导入模块的语法错误
在prog.py里你写的是from clss.py import *,正确的导入应该去掉.py后缀:
from clss import *
把这些问题都修复后,每个B实例就会拥有自己独立的c属性,不会被其他实例覆盖,也能正确处理CSV里的值啦!
内容的提问来源于stack exchange,提问作者H S

