标签:list 支持 整数 garbage 修改 对象 lin and 结果
本章章节:
翻译过来叫做变量,其实就是指针/标签。指向一个内存地址。而别名就是说同一个对象有多个标签。
完全一样的两个对象,区别它们的是identity,Python使用id()函数得到一个对象的identity。
==符号是object.__eq__的语法糖。它会调用内存中的对象进行比较。
is符号是object.__id__的语法糖,只会比较对象的id,自然运行速度快于==。
tuple模式是浅层复制。使用list()或者copy()复制的是tuple内的第一层对象。
可用于深层的复制。
copy.copy(x)返回x层的浅层复制。
call by sharing共享传参。这是Pyhon唯一支持的参数传递模式。Ruby等OO对象语言都是这种模式。
一个函数可以改变传递给它,作为参数的可变对象(multable object)的值,但不能改变对象的identity。
例子:
def f(a, b): print(id(a), id(b)) # a += b print(id(a)) return a x = 1 print("id(x) is %s" % id(x)) y = 2 print("id(y) is %s" % id(y)) f(x, y)
id(x) is 4565326480 id(y) is 4565326512 4565326480 4565326512 4565326544
由此可知,x和a, y和b都是同一个对象的引用。所以说a, b只是别名。
而a += b代码中的a, 的id改变了。这代表它引用的是另一个不可变对象(整数)。
对上面的例子进行修改:
def f(a, b): print(id(a), id(b)) # a += bprint("change variable a, but its id not change: {}".format(id(a))) return a x = [1, 2] print("id(x) is %s" % id(x)) y = [2, 3] print("id(y) is %s" % id(y)) print("return is {}".format(f(x, y))) print("x is {}".format(x))
x是一个list,属于可变对象。
id(x) is 4545995264
id(y) is 4545996928
4545995264 4545996928
change variable a, but its id not change: 4545995264
return is [1, 2, 2, 3]
x is [1, 2, 2, 3]
由此验证了一个函数可以改变传递给它,作为参数的可变对象(multable object)的值,但不能改变对象的identity。
如果把x,y改成一个tuple,那么函数不能对x进行修改了。
这个原理体现了一些方便。但是:
class HauntedBus: def __init__(self, passengers = []): self.passengers = passengers def pick(self, name): self.passengers.append(name)
bus1 = HauntedBus() bus1.passengers.append("Tom") print("bus1 has {}".format(bus1.passengers)) bus2 = HauntedBus() print("bus2 has {}".format(bus2.passengers))
结果竟然是:
bus1 has [‘Tom‘] bus2 has [‘Tom‘]
bus2也有了一个乘客Tom!
原因就是因为它们共享了一个参数passengers,它是一个list类型,是可变参数。由于共享,所以出现了两个对象数据混淆的问题。
背后的过程是:passengers = []是在模块加载时,定义函数的过程中被计算。
避免也简单,如果需要传入数据,在函数内进行复制,使用复制的数据。
《流畅的Python》Object References, Mutability, and Recycling--第8章
标签:list 支持 整数 garbage 修改 对象 lin and 结果
原文地址:https://www.cnblogs.com/chentianwei/p/12042188.html