>>>a = 'runoob'
>>> id(a)
4531887632
>>> b = 1
>>> id(b)
140588731085608
>>> charles = {'name': 'Charles L. Dodgson', 'born': 1832}
# lewis是charles的别名
>>> lewis = charles
>>> lewis is charles
True
>>> id(charles), id(lewis)
(4300473992, 4300473992)
# 向lewis中添加一个元素相等于向charles中添加一个元素
>>> lewis['balance'] = 950
>>> charles
{'name': 'Charles L. Dodgson', 'balance': 950, 'born': 1832}
>>> alex = {'name': 'Charles L. Dodgson', 'born': 1832}
# 比较两个对象,结果相等,这是因为dict 类的__eq__ 方法就是这样实现的
>>> alex == charles
True
# 但它们是不同的对象。这是Python 说明标识不同的方式:a is not b
>>> alex is not charles
True
在上述代码中,lewis 和charles 是别名,即两个变量绑定同一个对象。而alex 不是charles 的别名,因为二者绑定的是不同的对象。alex 和charles 绑定的对象具有相同的值(== 比较的就是值),但是它们的标识不同。
对象ID 的真正意义在不同的实现中有所不同。在CPython 中,id() 返回对象的内存地址,
但是在其他Python 解释器中可能是别的值。关键是,ID 一定是唯一的数值标注,而且在
对象的生命周期中绝不会变。
== 运算符比较两个对象的值(对象中保存的数据),而is 比较对象的标识。通常,我们关注的是值,而不是标识,因此Python 代码中== 出现的频率比is 高。
然而,在变量和单例值之间比较时,应该使用is。目前,最常使用is 检查变量绑定的值是不是None。下面是推荐的写法:
x is None
否定的正确写法是:
x is not None
is 运算符比== 速度快,因为它不能重载,所以Python 不用寻找并调用特殊方法,而是直接比较两个整数ID。而a == b 是语法糖,等同于a.__eq__(b)
不可变对象示例
>>> a = 1
>>> id(a)
7068776
>>> b = a
>>> id(b)
7068776
>>> a += 1
# 重新赋值之后,变量a的内存地址已经变了
>>> id(a)
7068752
>>> a
2
>>> b
1
>>> id(b)
7068776
# 执行a=1后开辟了一块内存存放1,然后b也指向1,执行a+=1后,因为整型不可变,所以又开辟了一块内存存放2,现在a指向2,b还指向1。
可变对象示例
>>> a = [1,1]
>>> id(a)
140687424863480
>>> b = a
>>> id(b)
140687424863480
>>> a.append(3)
>>> b
[1, 1, 3]
>>> a
[1, 1, 3]
# 执行a = [1, 1]后,a指向这个列表,执行b = a后,b也指向这个列表,两个变量指向同一块内存。执行a.append(3)之后,因为列表是可变对象,append操作知识改变了其值,内存地址并没有变.
python中一切都是对象,参数传递都是对象的引用,具体的,如果函数收到的是可变对象(如列表字典),则可以修改对象的原始值;如果是不可变对象(整型浮点型字符元组),就不能修改原始对象。
python的参数传递分为两种情况:
来看几个例子:
参数为不可变对象:
def add(num):
num = num + 10
d = 2
add(d)
print(d)
# 输出结果为2, 因为整数是不可变对象,执行num=num+10后,会产生新的对象,重新开辟一块内存存放12,num指向12, 而d没有变化
参数为可变对象
def add(nums):
nums.append(3)
d = [1,2]
add(d)
print(d)
# 输出结果为[1,2,3]。执行add方法时,nums指向[1,2]。因为列表是可变对象,直接在nums进行操作不会产生新的对象,所以返回[1,2,3]
b=a, 赋值引用,a和b都指向同一个对象
b = a.copy(): 浅拷贝, a 和 b 是一个独立的对象,但他们的子对象还是指向统一对象(是引用)
b = copy.deepcopy(a): 深度拷贝, a 和 b 完全拷贝了父对象及其子对象,两者是完全独立的。
#!/usr/bin/python
import copy
a = [1, 2, 3, 4, ['a', 'b']] #原始对象
b = a #赋值,传对象的引用
c = copy.copy(a) #对象拷贝,浅拷贝
d = copy.deepcopy(a) #对象拷贝,深拷贝
a.append(5) #修改对象a
a[4].append('c') #修改对象a中的['a', 'b']数组对象
print( 'a = ', a )
print( 'b = ', b )
print( 'c = ', c )
print( 'd = ', d )
'''输出结果
a = [1, 2, 3, 4, ['a', 'b', 'c'], 5]
b = [1, 2, 3, 4, ['a', 'b', 'c'], 5]
c = [1, 2, 3, 4, ['a', 'b', 'c']]
d = [1, 2, 3, 4, ['a', 'b']]
'''
总结如下: