15-Python对象的比较、拷贝
2021-04-22 21:33
标签:e30 文档 无法访问 ccf 更新 这一 pen cts str 我们首先来看,下面的Python代码示例: 这里首先将1赋值于a,即a指向了1这个对象,如下面的流程图所示: 接着b = a则表示,让变量b也同时指向1这个对象。这里要注意,Python里的对象可以被多个变量所指向或引用。 最后执行a = a + 1。需要注意的是,Python的数据类型,例如整型(int)、字符串(string)等等,是不可变的。所以,a = a + 1,并不是让a的值增加1,而是表示重新创建了一个新的值为2的对象,并让a指向它。但是b仍然不变,仍然指向1这个对象。 因此,最后的结果是,a的值变成了2,而b的值不变仍然是1。 通过这个例子你可以看到,这里的a和b,开始只是两个指向同一个对象的变量而已,或者你也可以把它们想象成同一个对象的两个名字。简单的赋值b = a,并不表示重新创建了新对象,只是让同一个对象被多个变量指向或引用。 同时,指向同一个对象,也并不意味着两个变量就被绑定到了一起。如果你给其中一个变量重新赋值,并不会影响其他变量的值。 明白了这个基本的变量赋值例子,我们再来看一个列表的例子: 同样的,我们首先让列表l1和l2同时指向了[1, 2, 3]这个对象。 由于列表是可变的,所以l1.append(4)不会创建新的列表,只是在原列表的末尾插入了元素4,变成[1, 2, 3, 4]。由于l1和l2同时指向这个列表,所以列表的变化会同时反映在l1和l2这两个变量上,那么,l1和l2的值就同时变为了[1, 2, 3, 4]。 另外,需要注意的是,Python里的变量可以被删除,但是对象无法被删除。比如下面的代码: del l 删除了l这个变量,从此以后你无法访问l,但是对象[1, 2, 3]仍然存在。Python程序运行时,其自带的垃圾回收系统会跟踪每个对象的引用。如果[1, 2, 3]除了l外,还在其他地方被引用,那就不会被回收,反之则会被回收。 由此可见,在Python中: 从上述Python变量的命名与赋值的原理讲解中,相信你能举一反三,大概猜出Python函数中参数是如何传递了吧? 这里首先引用Python官方文档中的一段说明: “Remember that arguments are passed by assignment in Python. Since assignment just creates references to objects, there’s no alias between an argument name in the caller and callee, and so no call-by-reference per Se.” 准确地说,Python的参数传递是赋值传递 (pass by assignment),或者叫作对象的引用传递(pass by object reference)。Python里所有的数据类型都是对象,所以参数传递时,只是让新变量与原变量指向相同的对象而已,并不存在值传递或是引用传递一说。 比如,我们来看下面这个例子: 这里的参数传递,使变量a和b同时指向了1这个对象。但当我们执行到b = 2时,系统会重新创建一个值为2的新对象,并让b指向它;而a仍然指向1这个对象。所以,a的值不变,仍然为1。 那么对于上述例子的情况,是不是就没有办法改变a的值了呢? 答案当然是否定的,我们只需稍作改变,让函数返回新变量,赋给a。这样,a就指向了一个新的值为2的对象,a的值也因此变为2。 不过,当可变对象当作参数传入函数里的时候,改变可变对象的值,就会影响所有指向它的变量。比如下面的例子: 这里l1和l2先是同时指向值为[1, 2, 3]的列表。不过,由于列表可变,执行append()函数,对其末尾加入新元素4时,变量l1和l2的值也都随之改变了。 但是,下面这个例子,看似都是给列表增加了一个新元素,却得到了明显不同的结果。 为什么l1仍然是[1, 2, 3],而不是[1, 2, 3, 4]呢? 要注意,这里l2 = l2 + [4],表示创建了一个“末尾加入元素4“的新列表,并让l2指向这个新的对象。这个过程与l1无关,因此l1的值不变。当然,同样的,如果要改变l1的值,我们就得让上述函数返回一个新列表,再赋予l1即可: 这里你尤其要记住的是,改变变量和重新赋值的区别: 至于my_func3()和my_func5()的用法,两者虽然写法不同,但实现的功能一致。不过,在实际工作应用中,我们往往倾向于类似my_func5()的写法,添加返回语句。这样更简洁明了,不易出错。 今天,我们一起学习了Python的变量及其赋值的基本原理,并且解释了Python中参数是如何传递的。和其他语言不同的是,Python中参数的传递既不是值传递,也不是引用传递,而是赋值传递,或者是叫对象的引用传递。 需要注意的是,这里的赋值或对象的引用传递,不是指向一个具体的内存地址,而是指向一个具体的对象。 清楚了这一点,如果你想通过一个函数来改变某个变量的值,通常有两种方法。一种是直接将可变数据类型(比如列表,字典,集合)当作参数传入,直接在其上修改;第二种则是创建一个新变量,来保存修改后的值,然后将其返回给原变量。在实际工作中,我们更倾向于使用后者,因为其表达清晰明了,不易出错。 15-Python对象的比较、拷贝 标签:e30 文档 无法访问 ccf 更新 这一 pen cts str 原文地址:https://www.cnblogs.com/ting152/p/13275422.html
‘==‘
表示比较对象间的值是否相等,而‘is‘
表示比较对象的标识是否相等,即它们是否指向同一个内存地址。‘is‘
效率优于‘==‘
,因为‘is‘
操作符无法被重载,执行‘is‘
操作只是简单的获取对象的ID,并进行比较;而‘==‘
操作符则会递归地遍历对象的所有值,并逐一比较。a = 1
b = a
a = a + 1
l1 = [1, 2, 3]
l2 = l1
l1.append(4)
l1
[1, 2, 3, 4]
l2
[1, 2, 3, 4]
l = [1, 2, 3]
del l
Python函数的参数传递
def my_func1(b):
b = 2
a = 1
my_func1(a)
a
1
def my_func2(b):
b = 2
return b
a = 1
a = my_func2(a)
a
2
def my_func3(l2):
l2.append(4)
l1 = [1, 2, 3]
my_func3(l1)
l1
[1, 2, 3, 4]
def my_func4(l2):
l2 = l2 + [4]
l1 = [1, 2, 3]
my_func4(l1)
l1
[1, 2, 3]
def my_func5(l2):
l2 = l2 + [4]
return l2
l1 = [1, 2, 3]
l1 = my_func5(l1)
l1
[1, 2, 3, 4]
总结