在学习 Python 的过程中,我为它的简洁优雅而痴迷,但它又是如此的调皮,在提供了很多舒服的功能特性之外,又悄悄挖了很多带有迷惑性的坑,令人防不胜防…

人不能两次踏入同一条河流,在无数次踩进同样的坑里之后,我觉得我有必要整理一下,一为自警,二为给大家提个醒,希望你不要和我犯相同的错误。

这会是一个系列,每篇 5 个,系列文章更新不定,不想错过的,记得点个关注,不迷路。

0x00 走丢的外部变量

首先我们先来看这么一个例子:

e = 429

try:

raise Exception()

except Exception as e:

pass

print(e)

PS:except Exception as e 可以捕获除了与程序退出(sys.exit())相关之外的所有异常。

在继续向下看之前,你可以先思考一下上述例子可能出现的结果是什么,也可以自己尝试着在编译器里输入一下。思考完了请继续往下看。

出现的结果如下:

Traceback (most recent call last):

File "test.py", line 8, in

print(e)

NameError: name 'e' is not defined

竟然报错了,那么这到底是为什么呢?

其实这是因为在 Python3 中使用 as 分配异常的时候,在 except 的末尾将会把这个异常清除掉(在 Python2 中则不会出现这样的情况)。这就好像将上面的示例变成下面的样子:

e = 429

try:

raise Exception()

except Exception as e:

try:

pass

finally:

del e

print(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(())

>>> tur = (1, 2)

>>> type(tur)

但是如果小括号内只有一个元素的话,比如像下面这样,它就是小括号内的元素类型:

>>> tur = (1)

>>> type(tur)

那么如果想要表示一个元素的元组咋整呢?要像下面这样:

>>> tur = (1, )

>>> type(tur)

加个逗号 “,” 就 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显示3位数不够0补位_关于Python开发中的那些坑总结,令人防不胜防,建议收藏!...相关推荐

  1. python显示圆周率的值是多少_用python做一个有趣的实验,看你的生日是否出现在圆周率中...

    原标题:用python做一个有趣的实验,看你的生日是否出现在圆周率中 前言: 看到圆周率这个词,突然冒出一个灵感怎么知道我的生日在不在圆周率的中又或者在第几位呢?带着这个想法去网上找了一堆数据,最后找 ...

  2. python的索引值从1开始还是0开始_为什么Python list的索引从0开始?

    python的创始人(Guido van Rossum)说过,Python使用0-based索引方式的原因之一是Python的切片(slice)语法. 先看看切片的用法.可能最常见的用法就是" ...

  3. python基础面试都问什么问题_基本 Python 面试问题

    def Stack(object): def __init__(self): self.stack = [] def push(self,value): # 进栈 self.stack.append( ...

  4. python 预测任意天后股票数据_在Python中使用LSTM进行股票市场预测

    本文概述 在本教程中, 你将看到如何使用称为长短期记忆的时间序列模型. LSTM模型功能强大, 特别是通过设计保留了长期记忆, 这一点将在以后看到.你将在本教程中解决以下主题: 了解为什么你需要能够预 ...

  5. python如何初始化一个二维数组_使用Python实现一个简单的商品期货布林指标突破策略...

    布林指标突破策略,思路非常简单.使用Python语言编写该策略,也非常容易实现,加上回测配置信息,有70行代码,实际可以更加精简,鉴于教学策略,没有使用难懂的Python语法,使用的是比较基础的语句. ...

  6. python程序设计课后答案第三单元_最新Python程序设计课后习题答案-第一单元

    精品文档 精品文档习题1 一.选择题 1.Python语言属于().C A.机器语言 B.汇编语言 C.高级语言 D.科学计算语言2.下列选项中,不属于Python特点的是().B A.面向对象 B. ...

  7. python查询和替换一个文本字符串_【Python】python面试题

    一些Python面试题 1. (1)python下多线程的限制以及多进程中传递参数的方式 python多线程有个全局解释器锁(global interpreter lock),这个锁的意思是任一时间只 ...

  8. python编辑七段数码管引脚图_少儿Python程序第十二讲:单片机控制数码管

    本讲继续学习用Python控制单片机,并用单片机连接和控制其它硬件,具体目标是利用开发板控制四位数码管,显示指定的数字.实验效果如图12.1所示:图12.1 单片机控制四位数码管显示数字 注意:请先把 ...

  9. python天勤金叉编程代码大全_这些Python编程黑科技,装逼指南,高逼格代码,让你惊叹不已...

    1.单行写一个评级组件 "★★★★★☆☆☆☆☆".slice(5 - rate, 10 - rate);定义一个变量rate是1到5的值,然后执行上面代码,看图 才发现插件什么的都 ...

最新文章

  1. Lync 2010迁移Lync 2013 PART6:迁移CMS
  2. BugkuCTF-reverse:入门逆向
  3. 网络时代:我只是一个用户
  4. 案例:用户登录(html--servlet--mysql)
  5. PHP服务端推送技术Long Polling
  6. Linux内存管理:《Aarch64 Kernel Memory Management.pptx》
  7. 一篇文章带你熟悉 TCP/IP 协议-(三)
  8. html5 graphics with svg css3,Using SVG with CSS3 and HTML5: Vector Graphics for Web Design
  9. 聊天机器人中的 A/B 测试
  10. 转载:VS2005 工具方便实用的快捷键。
  11. 【前端工程化】使用tippy.js代替自定义的popover/tooltip
  12. python傅里叶变换 信号处理 序列_(十六)数字图像处理中的傅里叶(DFT/FFT)
  13. 从联立方程式看机器学习的数学模式
  14. 瑞吉外卖项目学习笔记:P1-项目介绍
  15. 安装NVIDIA显卡驱动以及CUDA
  16. input文本框输入溢出的时候,鼠标悬停显示全部信息
  17. Jenkins Windons下安装ChangeLog插件获取Git更新日志
  18. 学习如何使用php创建一张空白的图片
  19. 数说故事2022年中国预制菜行业趋势及营销创新洞察报告
  20. 磁盘黑色未分配区域恢复成绿色逻辑分区

热门文章

  1. Kotlin+Retrofit + MVVM 的网络请求框架的封装
  2. 小陈Java学习笔记0810
  3. python文件管理_python——文件管理
  4. 伊利诺理工大学计算机科学硕士,美国伊利诺伊理工大学计算机科学硕士
  5. 智谱AI多项成果惊艳亮相2021北京智源大会
  6. Googleearth提取数字高程等高线
  7. springmvc之响应类型,string,void,ModelAndView
  8. jquery遍历json数组
  9. ailx10的hacknet攻略004
  10. shell学习之awk