一般情况下,我们知道 在 python 中,strings, tuples, 和 numbers 是不可更改的对象,而 list,dict 等则是可以修改的对象
当把list和dict当参数传入函数时,强制为引用传值(即:在函数内部修改了对象,函数外部的对象也会改变)
def update_remark(data): print('函数里修改了remak为:已修改') data['remark'] = '已修改' return data['remark'] dict1 = {'remark': '测试'} print('外面里remark:', end=' ') print(dict1) update_remark(dict1) print('外面里remark:', end=' ') print(dict1)
执行结果如下:
这个问题也不大,写函数的时候注意一下就好了。
问题是:一个类实例化出两个对象,修改各自对象的属性,数据还能被引用了??
测试代码如下:
class Demo: name = '' data = {} def __init__(self): pass def set_name(self, name): self.name = name def get_name(self): return self.name def set_data(self, key, value): self.data[key] = value def get_data(self, key): return self.data[key] if key in self.data else None if __name__ == '__main__': obj1 = Demo() obj2 = Demo() print(obj1) print(obj2) obj1.set_name('实例1') obj2.set_name('实例2') print(obj1.get_name()) print(obj2.get_name()) obj1.set_data('remark', '测试') print(obj1.get_data('remark')) print(obj2.get_data('remark'))
执行结果如下:
这下就头大了,我只修改了obj1对象里的 data 属性,为何 obj2 里的 data 属性也跟着变了??
实例化对象之后,可变类型的属性居然还是引用传值的??
解决办法:不要直接在类的顶部里初始化属性,在构造方法里初始化属性才不会出错
类顶部的属性可以直接不写,在 __init__ 构造函数里用"self.属性名 = 属性值" 这种方式设置类的属性就可以了
注:强迫症一定要在类的顶部写属性的话,__init__ 里也还重新初始化一下
修改后的类如下:
class Demo: def __init__(self): self.name = '' self.data = {} def set_name(self, name): self.name = name def get_name(self): return self.name def set_data(self, key, value): self.data[key] = value def get_data(self, key): return self.data[key] if key in self.data else None if __name__ == '__main__': obj1 = Demo() obj2 = Demo() print(obj1) print(obj2) obj1.set_name('实例1') obj2.set_name('实例2') print(obj1.get_name()) print(obj2.get_name()) obj1.set_data('remark', '测试') print(obj1.get_data('remark')) print(obj2.get_data('remark'))
执行结果如下:
不知道是Python的bug还是本来就是这样设计的,总之:引以为戒!!