Python里的那些坑

举报
G-washington 发表于 2019/12/13 17:06:45 2019/12/13
【摘要】 Python是一门清晰简洁的语言,如果你对一些细节不了解的话,就会掉入到那些深不见底的“坑”里,下面,我就来总结一些Python里常见的坑。

Python里的那些坑

  • Python是一门清晰简洁的语言,如果你对一些细节不了解的话,就会掉入到那些深不见底的“坑”里,下面,我就来总结一些Python里常见的坑。

列表创建和引用

嵌套列表的创建

  • 使用*号来创建一个嵌套的list:

image.png

通过这个方法,可以得到一个包含3个list的嵌套list,我们来给第一个list增加一个元素:

image.png

通过输出的结果可以看初,我们只给第一元素增加元素,结果三个list都增加了一个元素。这是因为[[]]*3并不是创建了三个不同list,而是创建了三个指向同一个list的对象,所以,当我们操作第一个元素时,其他两个元素内容也会发生变化的原因。效果等同于下面这段代码:

image.png

我们可以打印出元素的内存地址一探究竟:


image.png

到这我们可以明白原因了。那如何解决了?可以这样:


image.png

这样我们就创建了三个不同的list对象

image.png

列表元素的引用

  • 不要使用索引方法遍历list,例如:

image.png

比较好的方法是:

image.png

for语句会自动生成一个迭代器。如果你需要索引位置和元素,使用enumerate函数:

image.png


注意 == 符号的使用

image.png

捕获异常由于提前检查

  • 不够优雅的代码:

image.png

比较好的做法:

image.png

在python2.6+的里面可以更简洁:

image.png


之所以这么用,是这么写更加通用,比如file_path给你传个None就瞎了,还得判断是不是None,如果不判断,就又得抓异常,判断的话,代码有多写了很多。

类变量初始化

  • 不要在对象的init函数之外初始化类属性,主要有两个问题

    错误示范(除非你想要静态变量)

    • 如果类属性更改,则初始值更改。

    • 如果将可变对象设置为默认值,您将获得跨实例共享的相同对象。


image.png


正确的做法:

image.png

函数默认参数

image.png

该代码的行为与预期的一样,但如果我们不传递参数呢?

image.png

这是因为函数参数类型是定义是确认的而不是运行时,所以在两次函数调用时,li指向的是同一个list对象,如果要解决这个问题,可以这样:

image.png

这虽然解决了上述的问题,但,其他的一些对象,比如零长度的字符串,输出的结果就不是我们想要的。

image.png

最常用的办法是检查参数是不是None

image.png

在遍历时修改

  • for语句在遍历对象是会生成一个迭代器,如果你在遍历的过程中修改对象,会产生意想不到的结果:

image.png

整数和字符串定义

  • python预先缓存了一个区间的整数用来减少内存的操作,但也正是如此,有时候会出很奇特的错误,例如:

  • image.png

  • 另外一个例子

  • image.png

  • 通过不断的测试,会发现(-3,256)这区间的整数都返回True,有的甚至是(-8,257)。默认情况下,[-5,256]会在解释器第一次启动时创建并缓存,所以才会有上面的奇怪的行为。这是个很常见但很容易被忽略的一个坑。解决方案是始终使用equality(==)运算符而不是 identity(is)运算符比较值。

  • Python还保留对常用字符串的引用,并且可以在比较is字符串的身份(即使用)时产生类似的混淆行为。

  • image.png

  • python字符串被缓存了,所有python字符串都是该对象的引用,对于不常见的字符串,即使字符串相等,比较身份也会失败。

  • image.png

  • 所以,就像整数规则一样,总是使用equal(==)运算符而不是 identity(is)运算符比较字符串值。

  • 列表推导和循环中的变量泄漏

  • 有个例子:

  • image.png

  • python2中列表推导改变了i变量的值,而python3修复了这个问题:


  • image.png

  • 类似地,for循环对于它们的迭代变量没有私有的作用域


  • image.png

  • 这种行为发生在Python 2和Python 3中。

    为了避免泄漏变量的问题,请在列表推导和for循环中使用新的变量。

  • or操作符

  • 例如

  • image.png

  • 这个很简单,但是,再看一个:

  • image.png

  • 这是由于or的优先级低于==,所以表达式将被评估为if (a) or (b) or (c == 3):。正确的方法是明确检查所有条件:

  • image.png

  • 或者,可以使用内置函数any()代替链接or运算符:

  • image.png

  • 或者,为了使其更有效率:

image.png

更加简短的写法:

image.png

转载自我的博客:http://www.bugcode.cn/Python%20Pitfalls.html


本文转载自异步社区

原文链接:https://www.epubit.com/articleDetails?id=NC7E3EF94AA700001A099DB85104017FF

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。