Python类初始化传字典调用类方法报错及方案合理性咨询
问题修复方案
1. 报错原因及修复
你遇到的NameError是因为构造字典时的键没有加引号:你写的{positive:True, even:True}中,Python会把positive、even当作变量名去解析,而这两个变量没有定义,自然报错。
同时你的代码还有一个隐藏bug:Python中不要用可变对象作为函数默认参数,def __init__(self, data, filter = {}): 写法会导致所有未传filter参数的实例共享同一个字典对象,后续修改会互相影响。
修复方式1:修改传参格式
把字典的键改为字符串即可:
record = Record(data, filter={"positive":True, "even":True})
同时修改__init__的默认参数规避可变对象问题:
def __init__(self, data, filter = None): self.data = data filter = filter or {} if filter: self.filter(**filter)
修复方式2:优化参数设计(更推荐)
直接把过滤参数作为__init__的关键字参数,不需要传字典,可读性更高:
class Record: def __init__(self, data, positive=False, even=False): self.data = data self.filter(positive=positive, even=even) def filter(self, positive = False, even = False): data_ = self.data if positive: data_ = [c for c in data_ if c>0] if even: data_ = [c for c in data_ if c % 2 ==0] self.data = data_ data = list(range(-5,10,1)) record = Record(data, positive=True, even=True) print(record.data) # 正确输出[2,4,6,8]
2. __init__中调用类方法的合理性
这个设计是合理的,只要满足两个前提:
- 调用的类方法仅操作已经完成初始化的实例属性,不会依赖__init__后续才会赋值的属性
- 不需要把该方法设计为被子类重写的方法,或者你明确需要利用多态特性让子类自定义初始化逻辑
这种写法的优势是可以复用逻辑,避免相同的过滤代码在__init__和filter方法中写两遍,符合DRY(不要重复代码)原则。
如果担心子类重写带来的不可控问题,可以把filter方法改为私有方法(加双下划线前缀__filter),避免被意外重写。
内容的提问来源于stack exchange,提问作者Dmitri
相关产品推荐
相关产品推荐

