Python 中那些令人防不胜防的坑(一)
大家好,我是 Rocky0429,一个正在学习 Python 的蒟蒻…
在学习 Python 的过程中,我为它的简洁优雅而痴迷,但它又是如此的调皮,在提供了很多舒服的功能特性之外,又悄悄挖了很多带有迷惑性的坑,令人防不胜防…
人不能两次踏入同一条河流,在无数次踩进同样的坑里之后,我觉得我有必要整理一下,一为自警,二为给大家提个醒,希望你不要和我犯相同的错误。
这会是一个系列,每篇 5 个,系列文章更新不定,不想错过的,记得点个关注,不迷路。
0x00 走丢的外部变量
首先我们先来看这么一个例子:
e = 429try:raise Exception()
except Exception as e:passprint(e)
PS:except Exception as e 可以捕获除了与程序退出(sys.exit())相关之外的所有异常。
在继续向下看之前,你可以先思考一下上述例子可能出现的结果是什么,也可以自己尝试着在编译器里输入一下。思考完了请继续往下看。
出现的结果如下:
Traceback (most recent call last):File "test.py", line 8, in <module>print(e)
NameError: name 'e' is not defined
竟然报错了,那么这到底是为什么呢?
其实这是因为在 Python3 中使用 as 分配异常的时候,在 except 的末尾将会把这个异常清除掉(在 Python2 中则不会出现这样的情况)。这就好像将上面的示例变成下面的样子:
e = 429try:raise Exception()
except Exception as e:try:passfinally:del eprint(e)
通过上面的变形代码,我们可以很清楚的看明白发生这一切的根源是什么:因为 e 被删除了。这也变相的告诉我们,如果想要在 except 后面引用 e,必须将它先赋值给其它变量。
这样看来,是变量 e 执行了 except 子句而被删除,但是为什么 e 会去执行 except 子句呢?仅仅是因为 e 和 as 后面的 e 长的一毛一样?
答案是否定的,其实这个是因为子句在 Python 中没有独立的作用域,所以上述示例中的所有内容都处于同一个作用域里,所以变量 e 会因为执行了 except 子句而被删除。
0x01 同样是加,却不一定等价
在我们来表示「加」这个概念的时候,一般我们会用两种方式:a = a + b或者是 a += b 。在很多人的概念里这两个其实就是一种,不分彼此,比如之前我就是这么认为的,直到有一天有人拿着下面的坑过来让我踩...
首先我们先来看第一个例子:
>>> a = [1,2,3]
>>> b = a
>>> a = a + [4,5,6]
一个很简单的例子,你知道此时的 a 和 b 分别是多少么?请先自己思考一下再继续向下看:
>>> a
[1, 2, 3, 4, 5, 6]
>>> b
[1, 2, 3]
估计很多人都会答对,表达式 a = a + [4,5,6] ,等号右边其实是形成了一个新的列表,最后让 a 引用了这个新的列表,而 b = a 引用的是之前的 a,所以 b 保持不变。
明白了上面的例子,我们接下来再看一个稍微有点区别的例子:
>>> a = [1,2,3]
>>> b = a
>>> a += [4,5,6]
上面的例子和文章开头的例子区别在从 + 变成了 +=,按照我们惯性思维去想,肯定以为这俩例子就是一个东西的两种不同写法而已,可实际上真的是这样吗?让我们来看一下此时的 a,b:
>>> a
[1, 2, 3, 4, 5, 6]
>>> b
[1, 2, 3, 4, 5, 6]
咦?同样是印象里的「加」,好像真的哪里有点不一样诶。。
通过上面我们就可以看出 a = a + b 和 a += b 并不总是表现相同,起码在列表上就是这么表现的。在这里的 a += [4,5,6] 实际上使用的是 extend 函数,所以 a 和 b 仍然指向已被修改的同一列表。
既然在这里说到了 + 和 +=,索性再多补充一点:在使用「加」的概念来连接字符串的时候,+= 其实比 + 的速度更快。
下面我们来实际的演示一下用 + 连接三个字符串:
>>> import timeit
>>> timeit.timeit("a = a + b + c", setup="a='a'*10000;b='b'*10000;c='c'*10000",number=100)
0.07921688999340404
>>> timeit.timeit("a += b + c", setup="a='a'*10000;b='b'*10000;c='c'*10000",number=100)
0.002059974998701364
上面的两个结果很容易看出来,在处理速度上,+= 比 + 处理的速度要快的多。出现这样现象的原因是 += 执行的是追加操作,追加操作的话就会比 + 少了一个销毁然后新建的动作,比如在 a += b + c 上 a 就不会被销毁。
0x02 不一般的小括号
很多学过别的编程语言的同学,很容易会忽略小括号 “()” 在 Python 中的一个重要表现,那就是小括号还能表示“元组” 这一不可变数据类型。
>>> type(())
<class 'tuple'>
>>> tur = (1, 2)
>>> type(tur)
<class 'tuple'>
但是如果小括号内只有一个元素的话,比如像下面这样,它就是小括号内的元素类型:
>>> tur = (1)
>>> type(tur)
<class 'int'>
天呐个天...
那么如果想要表示一个元素的元组咋整呢?要像下面这样:
>>> tur = (1, )
>>> type(tur)
<class 'tuple'>
加个逗号 “,” 就 ok 啦...
0x03 列表的删除没有那么简单
假如我们有一个列表,我想删除列表中的元素:
>>> lst = [1, 2, 3, 4, 5]
>>> for i in lst:
... lst.remove(i)
在刚开始学习 Python 之初,这是很多同学容易想到的做法,然而我们来看一下程序运行完以后的结果:
>>> lst
[2, 4]
看到这个结果,我...
这是为啥子呢?是因为在 for 循环中,如果我们删除了 index = 0 (即 1)的值,原本 index = 1 及其之后的值会向前补位,所以当前 index = 1 的值为之前 index = 2 的值。
列表的删除操作我们经常要用,所以大家要打起十二分的精神来对它。
0x04 is not 不分家
is not 在 Python 中是一伙的,用的时候要靠在一起,分开以后就是两个东西,结果会不一样…
>>> [1, 2, 3] is not None
True
>>> [1, 2, 3] is (not None)
False
这就在于,is not 是个单独的二元运算符,当它两侧的变量指向同一个对象的时候,结果为 False,否则结果为 True,希望引起大家的注意...
❤️ 看完有所收获?希望爱学习的你不要吝啬三连击哟[点赞 + 收藏 + 评论]~
另外本蒟蒻把公众号的高分原创文章整理成了一本电子书,取名《Python修炼之道》,一共 400 页!
具体内容请戳:熬夜爆肝整理 400 页 《Python 修炼之道》,一本高分原创高清电子书送给你!
目录如下:
现在免费送给大家,在我的公众号Python空间(微信搜 Devtogether) 回复 修炼之道即可获取。
作者Info:
【作者】:Rocky0429
【原创公众号】:Python空间。
【简介】:CSDN 博客专家, 985 计算机在读研究生,ACM 退役狗 & 亚洲区域赛银奖划水选手。这是一个坚持原创的技术公众号,专注Python 编程,每天坚持推送各种 Python 基础/进阶文章,数据分析,爬虫实战,数据结构与算法,不定期分享各类资源。
【转载说明】:转载请说明出处,谢谢合作!~
Python 中那些令人防不胜防的坑(一)相关推荐
- python中json.dumps使用的坑以及字符编码
我们知道,python中的字符串分普通字符串和unicode字符串,一般从数据库中读取的字符串会自动被转换为unicode字符串 下面回到重点,使用json.dumps时,一般的用法为: >&g ...
- Python 中非常狗的一个坑(在 `a={1:2},`后面多了一个逗号,自动被判为 tuple 类型了)
本意是好的,语法灵活一点,随意一点,用起来方便. 可是不限制声明类型,甚至元组的声明都不用加括号,这就有点狗了. a = {'a': 2} # a 是 dict a['a'] # a['a'] 是 2 ...
- python中var是什么变量_一、 Python概述、变量
一. Python概述 1.python是一门面向对象,解释型的脚本语言.语法简洁,编写效率高,但是执行(底层运行)效率低(总的来说解释语言执行效率低于编译语言). 注意:本博客所有的代 ...
- python显示3位数不够0补位_关于Python开发中的那些坑总结,令人防不胜防,建议收藏!...
在学习 Python 的过程中,我为它的简洁优雅而痴迷,但它又是如此的调皮,在提供了很多舒服的功能特性之外,又悄悄挖了很多带有迷惑性的坑,令人防不胜防- 人不能两次踏入同一条河流,在无数次踩进同样的坑 ...
- 原创关于python中的一些坑点
一.range ().map().filter(). dict.items()在python2.7返回列表,而在3.x中返回迭代器.当然迭代器大多数都是比较好的选择,更加pythonic,但是也有缺点 ...
- 正确姿势避坑 Python 中的6个典型错误
点击关注我哦 一篇文章带你使用正确姿势避坑 Python 中的6个典型错误 Python是一种高级的动态脚本语言.它易于使用的特性使得它非常流行,并且在最近几年得到了扩展.易用性也从易滥用开始.我们列 ...
- python中拼接路径os.path.join的坑
1.第一个坑 python中os.path.join的用法如下: import osos.path.join('path1', 'path2', 'pathn') 可以将多个路径进行拼接,但是需要注意 ...
- python工程师薪资坑吗-Python中反人类直觉的特性,你踩过坑吗?
Python是一个基于C语言实现的解释型高级语言, 提供了很多舒适的功能特性,使用起来非常方便.但有的时候, Python的输出结果,让我们感觉一头雾水,其中原因自然是Python语言内部实现导致的, ...
- 初学者都在坑里!不要在Python中使用“+”来连接字符串
很多初学者都像我一样,最开始使用Python时,会不自觉地使用"+"来连接字符串,就像在许多其他编程语言(比如Java)中那样,因为这样既直观又容易. 很多人学习python,不知 ...
- python中pymysql的小坑
python中pymyql的版本 这个版本跟0.9相差比较大,首先你执行完sql语句之后,一定进行commit提交 # 示例代码 cur = self.con.cursor() res = cur.e ...
最新文章
- 查询页面代码运行时间
- Nginx配置https,反向代理多实例tomcat的操作记录
- ASP调用存储过程详解。
- Get SQL String From Query Object In Entity Framework
- Silverlight WCF 上传实现
- Spark SQL程序操作HiveContext
- 快学Scala 第二课 (apply, if表达式,循环,函数的带名参数,可变长参数,异常)...
- 什么是中国1号信令?
- 通过使用CSS字体阴影效果解决hover图片时显示文字看不清的问题
- dj打碟怎么学_学DJ打碟 - Rane声卡连接
- Mysql(三)——(cmd)数据库的命令操作
- 【XXE】XXE漏洞攻击与防御
- Process打开文件
- 【leetcode】复写零
- 【Python】32 个常用入门 Python 实现
- [HNOI2010]PLANAR
- 使用ildasm反编译修改c# dll
- 向量的方向余弦公式_方向余弦怎么求
- 计算噪声方差的函数 matlab,噪声强度(噪声功率) 噪声方差到底有什么关系? matlab中的awgn函数...
- 单反相机参数之光圈、快门篇