为何修改单个Class实例属性时,所有实例均被改动?
问题:修改Unit1属性时Unit2意外被改动
我创建了Unit类的两个对象(Unit1、Unit2)以及Flow类的一个对象(FlowA)。调用FlowA的set_destination方法修改Unit1的属性时,Unit2的属性也被意外改动,尽管两者内存地址不同,且方法理论上仅修改传入参数对应的对象。
相关代码
import numpy as np allflows = [] processunits = [] class Flow: def __init__(self, name = '', components = '', flow_type = '', temperature=25, pressure = 1, composition = [1], origin = None, destination = None, mass_flow_rate = 0, elec_flow_rate = 0, heat_flow_rate = 0, is_calc_flow = False): self.attributes = {'name' : name, 'components' : components, 'flow_type' : flow_type, 'temperature' : temperature, 'pressure': pressure, 'composition' : composition, 'origin' : origin, 'destination' : destination, 'mass_flow_rate': mass_flow_rate, 'elec_flow_rate' : elec_flow_rate, 'heat_flow_rate': heat_flow_rate} self.is_calc_flow = is_calc_flow def set_destination(self, Destination_unit): if self.attributes['destination'] == Destination_unit.name and self.attributes['name'] in Destination_unit.input_flows: pass # Do nothing if already correctly assigned elif self.attributes['destination'] != Destination_unit.name: if self.attributes['destination']: # Remove from previous destination if exists prev_unit = next((unit for unit in processunits if unit.name == self.attributes['destination']), None) if prev_unit: prev_unit.input_flows.remove(self.attributes['name']) # Add to new destination Destination_unit.input_flows.append(self.attributes['name']) self.attributes['destination'] = Destination_unit.name print(f"Flow {self.attributes['name']} set destination to {self.attributes['destination']}") class Unit: def __init__(self, name, input_flows = [], output_flows = [], calculations = {}, expected_flows_in = [], expected_flows_out = [], coefficients = [], is_calc = False): self.name = name self.input_flows = input_flows self.output_flows = output_flows self.calculations = calculations self.expected_flows_in = expected_flows_in self.expected_flows_out = expected_flows_out self.coefficients = coefficients self.is_calc = is_calc Unit1 = Unit('Unit 1') Unit2 = Unit('Unit 2') Unit1.expected_flows_in = ['A'] Unit1.expected_flows_out = ['B', 'D'] Unit1.coefficients = 0.6 def Unit1func(flow, coeff): a_amount = flow.attributes['mass_flow_rate'] b_amount = coeff*a_amount d_amount = a_amount - b_amount return [{'name' : 'B', 'components' : 'B', 'mass_flow_rate' : b_amount, 'flow_type': 'Process stream', 'In or out' : 'Out'}, {'name' : 'D', 'components' : 'D', 'mass_flow_rate' : d_amount, 'flow_type': 'Process stream', 'In or out' : 'Out'}] FlowA = Flow('A', 'A','input', 25, 1, [1], np.nan , np.nan, 1000, np.nan, np.nan) print(f"Initial input flows of Unit2: {Unit2.input_flows}") print(f"Initial output flows of Unit2: {Unit2.output_flows}") FlowA.set_destination(Unit1) print(f"Input flows of Unit2 after setting FlowA's destination to Unit1: {Unit2.input_flows}") print(f"Output flows of Unit2 after setting FlowA's destination to Unit1: {Unit2.output_flows}") print(Unit1) print(Unit2)
控制台输出
Initial input flows of Unit2: [] Initial output flows of Unit2: [] Flow A set destination to Unit 1 Input flows of Unit2 after setting FlowA's destination to Unit1: ['A'] Output flows of Unit2 after setting FlowA's destination to Unit1: [] <__main__.Unit object at 0x0000022BDCB9CC50> <__main__.Unit object at 0x0000022BDCB9F500>
问题原因
核心问题出在Unit类的__init__方法使用了可变对象作为默认参数。Python中,可变对象(如列表[]、字典{})作为函数默认参数时,会在类定义阶段就创建,而不是每次实例化对象时重新创建。这意味着所有没有显式传入input_flows、output_flows等参数的Unit实例,都会共享同一个默认列表/字典对象。
所以Unit1和Unit2的input_flows指向的是同一个列表,当你调用Destination_unit.input_flows.append()修改Unit1的input_flows时,本质上是在修改这个共享的列表,因此Unit2的input_flows也会同步变化。
解决办法
修改Unit类的__init__方法,将可变默认参数改为None,然后在方法内部初始化独立的可变对象,确保每个实例拥有自己的列表/字典:
class Unit: def __init__(self, name, input_flows=None, output_flows=None, calculations=None, expected_flows_in=None, expected_flows_out=None, coefficients=None, is_calc=False): self.name = name # 初始化独立的列表/字典,避免实例共享 self.input_flows = input_flows if input_flows is not None else [] self.output_flows = output_flows if output_flows is not None else [] self.calculations = calculations if calculations is not None else {} self.expected_flows_in = expected_flows_in if expected_flows_in is not None else [] self.expected_flows_out = expected_flows_out if expected_flows_out is not None else [] self.coefficients = coefficients if coefficients is not None else [] self.is_calc = is_calc
这样修改后,每个Unit实例的input_flows等属性都是独立的对象,修改一个实例的属性不会影响其他实例。
内容的提问来源于stack exchange,提问作者Antoine Merlo
相关产品推荐
相关产品推荐

