Python 笔试集(1):关于 Python 链式赋值的坑
前言
Python 的链式赋值是一种简易型批量赋值语句,一行代码即可为多个变量同时进行赋值。
例如:
x = y = z = 1
链式赋值是一种非常优雅的赋值方式,简单、高效且实用。但同时它也是一个危险的糖衣炸弹,值得我们引起关注。
面试题:求链式赋值语句中变量 x 的值?
x = [1, 2, 3, 4, 5]
i = 0
i = x[i] = 3
- 如果你有过 C 语言的编程经验,那么你的思维习惯可能会让你得出这样的结果:x[0] 被赋值为 3,然后 i 再被赋值为 3,所以变量 x 的值为
[3, 2, 3, 4, 5]。 - 但实际上正确的答案却是:变量 i 首先被赋值为 3,然后 x[3] 再被赋值为3,所以最终变量 x 的值为
[1, 2, 3, 3, 5]。
从上述结果的表现可以看出二者的区别为:C 语言的赋值顺序是 自右往左* 依次进行的,而 Python 则相反。*
造成这种表征区别的本质原因是由于 C 语言是一种「值语义」类型语言,而 Python 是「对象语义」类型语言。
值语义类型编程语言
值语义指使用系统标准的拷贝方式将一个源对象拷贝成为目标对象后,源对象与目标对象之间毫无关系,彼此独立存在,改变互不影响。
从这一特性出发, C 语言的赋值语句被设计成了具有返回值的表达式,如此才能够保证在链式赋值中所有的对象最终都是彼此独立的。
例如:
x = (y = 1)
表达式 y = 1 在将数值 1 赋值给对象 y 之后返回了数值 1 ,最后再将返回的数值 1 赋值给对象 x。虽然两次赋值操作的数值都是 1,但实际上 x 和 y 对象在内存中的地址是不相同的,所以 x 和 y 彼此独立。
对象语义类型编程语言
对象语义,也称为引用语义。指使用系统标准的拷贝方式将一个源对象拷贝成为目标对象后,源对象与目标对象之间依然共享底层资源,对任意一方的改变都将影响到另一方。
由于不需要像 C 语言那般要求对象之间的独立性。所以,Python 的赋值语句就仅仅是一条语句,而非表达式,也就不存在返回值。在 Python 的定义中,表达式是由操作符(Operator)连接而成的语句,但等号 = 并不属于 Python 的操作符,而是分隔符(Delimiters)。所以下列语句在 Python 中是非法的。
In : x = (y = 1)
File "<ipython-input-6-f6b416f5f895>", line 1
x = (y = 1)
^
SyntaxError: invalid syntax
因为 y = 1 并没有返回值,所以最后执行的是将 “没有返回值” 赋值给了变量 x,显然这样的语义是不存在意义的。
最后
从使用的角度来说,我们只需要简单的记住 Python 的链式赋值顺序是 自左往右 的即可。但更重要的是,通过该面试题我们了解到了 Python 实现的语义类型为对象语义,以及对象语义和值语义的区别。这非常有助于我们以后理解、解决或避免 Python 大多数隐含的坑。
Python 笔试集(1):关于 Python 链式赋值的坑的更多相关文章
- Python 笔试集(4):True + True == ?
目录 目录 前文列表 面试题True Ture 布尔值 布尔类型是特殊的整数类型 前文列表 Python 笔试集:什么时候 i = i + 1 并不等于 i += 1? Python 笔试集(1):关 ...
- python学习(二十一) Python 中的链式赋值
Python的链式赋值如下:
- Python特色的序列解包、链式赋值、链式比较
一.序列解包 序列解包(或可迭代对象解包):解包就是从序列中取出其中的元素的过程,将一个序列(或任何可迭代对象)解包,并将得到的值存储到一系列变量中. 一般情况下要解包的序列包含的元素个数必须与你在等 ...
- 第4.7节 Python特色的序列解包、链式赋值、链式比较
一.序列解包 序列解包(或可迭代对象解包):解包就是从序列中取出其中的元素的过程,将一个序列(或任何可迭代对象)解包,并将得到的值存储到一系列变量中. 一般情况下要解包的序列包含的元素个数必须与你在等 ...
- Python链式赋值执行顺序及执行方式的证明
专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 老猿学5G博文目录 在<关于Python链式赋值的赋值顺序问题& ...
- 关于Python链式赋值的赋值顺序问题
在<第4.7节 Python特色的序列解包.链式赋值.链式比较>一文中,老猿这样介绍的: 链式赋值是用一行语句将多个变量赋值为同一个值,语法如下: 变量1=变量2=变量n=赋值表达式 该语 ...
- pyhton链式赋值在可变类型/不可变类型上的区别以及其本质
关于链式赋值的一些注意点: a=[]b=[]x=y=[]print(a==b) #Trueprint(x==y) #Trueprint(a is b) #Falseprint(x is y) #Tru ...
- DataFrame 链式赋值
在运行以下Python代码时,Pandas抛出SettingWithCopyWarning警告: row_data = df_pred.loc[key] row_data['col'] = new_v ...
- python和go对比字符串的链式处理
一.什么是链式处理 对数据的操作进行多步骤的处理称为链式处理,链式处理器是一种常见的编程设计,链式处理的开发思想将数据和操作拆分,解耦,让开发者可以根据自己的技术优势和需求,进行系统开发,同时将自己的 ...
随机推荐
- 一、移动端商城 Vue 组件库
一.组件库 移动端商城 Vue 组件库
- php产品细节图多图上传示例代码 无刷新
前台文件代码 upload.html <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" " ...
- 安装虚拟环境 virtualenv
前言 玩python 当然需要安装虚拟环境,这样就万一有多个项目,避免会冲突,如何安装 virtualenv: 下面如下: 输入 pip list cmd 你的电脑: 然后 输入 pip list: ...
- redux 中的 redux-thunk(中间件)
前言 空闲时间把redux中的redux-thunk中间件回顾下,因为以前没有写博客的习惯,都怪自己太年轻,好了 其实: redux的核心概念其实很简单:将需要修改的state都存入到sto ...
- js支持中文的hex编码 bin2hex (utf-8)
背景: 最近对接接口的时候需要将请求参数转为16进制,因此研究了下这个bin2hex.在js中转16进制 使用的是: str.charCodeAt(i).toString(16); 在遇到中文的时候编 ...
- SpringBoot与jackson.databind兼容报错问题
SpringBoot与jackson.databind兼容报错问题 ———————————————— 1.SpringBoot版本V2.0.0其依赖的jackson-databind版本为V2.9.4 ...
- 多线程——Java中继承Thread类与实现Runnable接口的区别
线程我只写过继承Thread类的,后来知道java多线程有三种方式,今天首先比较一下常用的继承Thread类和实现Runnable接口的区别. 按着Ctrl键进入Thread之后,发现Thread类也 ...
- python Tkinter 组件
Tkinter的提供各种控件,如按钮,标签和文本框,一个GUI应用程序中使用.这些控件通常被称为控件或者部件. 目前有15种Tkinter的部件.我们提出这些部件以及一个简短的介绍,在下面的表: 控件 ...
- MongoDB操作:insert()
@Override public boolean inSert(String dbName, String collectionName, String[] keys, Object[] values ...
- sh_11_九九乘法表
sh_11_九九乘法表 # 1. 打印 9 行小星星 row = 1 while row <= 9: col = 1 while col <= row: # print("*&q ...