资讯专栏INFORMATION COLUMN

Python: 今天你赋值了吗?

z2xy / 3074人阅读

摘要:没想到会被转发。看来眼球多了的确容易纠错。有时候你已经用它写了数万行代码,自以为很熟了。赋值最简单的赋值到底发生了什么呢一个变量被赋值了太笼统了吧。也就是说是把同一个对象传给了。这里,所绑定的对象的确被传进来了,的确生成了一个新对象。

[EDIT] 没想到会被转发。很高兴也很囧。看来眼球多了的确容易纠错。要小心啊小心。

编程语言就是这样。有时候你已经用它写了数万行代码,自以为很熟了。知道某一天遇到一个意料之外的问题。然后你才发现,原来TMD是这样的。

问题
def change(l1, l2):
    l1.append(10)
    l2 = [7, 5, 3, 1]


list1 = [1, 3, 5, 7]
list2 = [3, 3, 3, 3]
change(list1, list2)
print(list1)
print(list2)

以上这段代码的输出是什么?如果你的答案是

[1, 3, 5, 7, 10]
[3, 3, 3, 3]

那么大牛请安静的离开。如果不是,可以读一下下面的故事。

赋值

最简单的赋值

list1 = [1, 3, 5, 7]

到底发生了什么呢?一个变量list1被赋值了?太笼统了吧。
对于Python来说,Everything is an object。上面这行代码其实是这样的:

创建一个list对象

创建一个名字

绑定

再来看个例子:

s1 = "hello"
s2 = "hello"
print(s1 is s2)

这个会输出什么?True! 因为是这样的:

创建一个string对象

创建名字s1并绑定到string对象

创建名字s2并绑定到string对象

s1s2绑定的是同一个对象!

涨姿势了。那么问题又来了:

l1 = [1, 3, 5, 7]
l2 = [1, 3, 5, 7]
print(l1 is l2)

结果是?。。。。。。一定是True了吧?错!

这里又有一个很重要的概念。Mutable 和 immutable。"hello"[1, 3, 5, 7]的区别就在于:前者是Immutable而后者是Mutable。对于可变的对象,Python会自动生成全新的对象,以确保各对象可以独立的变动。而不可变的就不需要 - 节省内存。

传参

回到开始的问题。当list1被传给change()的时候,到底是什么被传过去了?让我们来做一个小实验。在传入前和change()内部各加入一个语句

print(id(list1))

print(id(l1))

这里要解释一下,Python的每一个对象都有一个唯一的hash id。id()这个函数就是用来打印出这个id的。加了上面两行之后,我们会发现。在change()函数之外与之内,两个值是一样的。也就是说Python是把同一个对象传给了change()

这下我们就可以理解为什么list1在调用了change()之后被改动了。但是那么list2也应该被改动了才对啊?非也。这里,list2所绑定的对象的确被传进来了,的确生成了一个新list对象。但是这个对象被绑定给了l2。跟list2没半毛钱关系。我们在做一个实验验证一下。

def change(l1, l2):
    l1.append(10)
    l2 = [7, 5, 3, 1]


list1 = [1, 3, 5, 7]
list2 = [3, 3, 3, 3]
change(list1, list2)
print(list1)
print(list2)

import dis
dis.dis(change)

对比开始的代码,我们加入了最后两句。这个两句使用了dis模块把change反编译了。结果如下:

2 0 LOAD_FAST 0 (l1)

          3 LOAD_ATTR                0 (append)
          6 LOAD_CONST               1 (10)
          9 CALL_FUNCTION            1
         12 POP_TOP

3 13 LOAD_CONST 2 (7)

         16 LOAD_CONST               3 (5)
         19 LOAD_CONST               4 (3)
         22 LOAD_CONST               5 (1)
         25 BUILD_LIST               4
         28 STORE_FAST               1 (l2)
         31 LOAD_CONST               0 (None)
         34 RETURN_VALUE

对应原来的行号3,我们可以看到,Python用4个常数build了一个list。然后把这个绑定到了名字l2然后就返回了。

至此真相大白。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/38150.html

相关文章

  • Python 进阶之路 (三) Tuple元组使用指南

    摘要:返回元组中元素最大值。将列表转换为元组。如果相对元组排序,通常先得将它转换为列表并使其成为一个可变对象,才能获得使用排序方法,或使用内置方法。 比List更安全的数据类型 大家好,今天为大家介绍一种更为安全的Python内置数据类型:tuple(元组),以及它的基础用法 元组是什么 元组(tuple)是另一种有序的数据类型,与list比较类似。主要不同的一点是tuple被创建后就不能对...

    1fe1se 评论0 收藏0
  • 我面试过没有上万人也有十几个,简历要这么写才有hr要

    摘要:所谓金三银四金九银十说的就是招聘季。大家想过没有,为什么是金三银四金九银十就连苹果输入法也知道这事情因为现在大多数的大学寒假都是放到月份前后,暑假是在月份前后。 今天终于有时间好好给大家写写关于如何写简历,给自己加分了。 这篇文章拖了很久了应该说,本来想在上周写的,但是事情实在是太多,又不想草草了事,所以搁置到现在。今天早上正好空出来了,就马上给大家码出来了。 showImg(http...

    0xE7A38A 评论0 收藏0
  • Python3,68个内置库函数详解,进阶必备,必须收藏!!!

    摘要:判断奇数是迭代器会根据提供的函数对指定序列做映射语法可以对可迭代对象中的每一个元素进行映射。 python内置库详解 1、引言2、内置库详解2.1 数据相关2.1...

    lindroid 评论0 收藏0
  • 《从零构建前后分离的web项目》:前端了解过关了吗?前端基础架构和硬核介绍

    摘要:前端准备前端了解过关了吗前端基础架构和硬核介绍技术栈的选择首先我们构建前端架构需要对前端生态圈有一切了解,并且最好带有一定的技术前瞻性,好的技术架构可能日后会方便的扩展,减少重构的次数,即使重构也不需要大动干戈,我通常选型技术栈会参考以下三 # 前端准备 :前端了解过关了吗?前端基础架构和硬核介绍 showImg(https://segmentfault.com/img/remote/...

    SwordFly 评论0 收藏0

发表评论

0条评论

z2xy

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<