知行编程网知行编程网  2022-03-13 03:00 知行编程网 隐藏边栏 |   抢沙发  5 
文章评分 0 次,平均分 0.0

菜鸟学Python的第150篇原创文章

阅读本文大概需要3分钟

菜鸟独白

Python语言虽然优美,简洁和强大,但是也有很多坑,一不小心就会掉进去。我学Python的时候也遇到过,今天总结一下,希望对大家能有收获!



1.陷阱1:可变默认参数

Python里面可变参数非常灵活,但是也有陷阱,不信你看看这个小例子:

据说80%学Python人,都会弄错的题

我们希望每次调用这个函数的,因为第二个参数是默认参数,如果不提供第二个参数,就会创建一个新的列表,然后返回列表,大家猜猜看结果应该是多少:

是不是应该为[1][2][3]. 


但是实际上结果为:

[1, 2, 3]

[1, 2, 3]

[1, 2, 3]

也就是说变量地址l1,l2被l3污染了,为啥呢:


当函数被第一次调用的时候,这个默认的res列表就被创建了,这个列表的地址空间就生成了!关键来了,Python的默认参数就被创建 一次,而不是每次调用函数的时候创建。也就是说,后面的代码对这个列表的改变,会前面的内容也同样修改!


不信的话,可以把res的地址打印出来看看:

据说80%学Python人,都会弄错的题

是不是地址都是一样的。


正确的做法:在每次函数调用时候,好的做法是把默认参数赋值为None来创建一个新的对象。

据说80%学Python人,都会弄错的题


高级进阶:爬虫递归的使用

有的同学说这确实是个陷阱,但是好像没有什么实际的用途,我们看一个爬虫额例子,前几周我刚在小密圈里面搞了一个爬虫的实战活动,里面就一个需要循环爬取,递归调用的场景!

我解析一个网页的页面,获得解析的结果,如果当前的页数超过了最大页数,则停止,否则继续递归解析下一页. 

据说80%学Python人,都会弄错的题

这里就用了res=None,递归还是蛮有用的。


2.陷阱2:闭包中延迟绑定

如果说上面的陷阱1还比较好理解,那下面的这个陷阱是就更有的迷惑性!大部分人都会掉进去,这就是Python在闭包作用域中绑定变量的方式~~

据说80%学Python人,都会弄错的题

我们有一个函数是squares(用来创建平方数的函数),里面有一个3个匿名函数,每个匿名函数是返回i的平方数.看起来好像也满简单的,返回平方数嘛


接着我们用一个for循环得到每一个square函数,然后给这个square输入一个2. 也就是说x为2.我们期望的结果是: 0,1,2

0*2=0

1*2=2

2*2=4


但是实际上的结果是:

4

4

4


为啥会这样的呢,闭包本来就是Python里面一个比较难理解的概念,经常和函数装饰器搞在一起,再加上一个匿名函数,头都昏了!我们来换一下普通函数方式来理解:

据说80%学Python人,都会弄错的题

Python的闭包是延迟绑定,也就是说闭包中用到的变量的值,是在内部函数被调用的时候才查询得到的。

res里面包含了闭包函数make_square,这个闭包比较牛逼,它会对延伸到函数的作用域外边,也就是包含了对变量i的绑定,最后一次查询i的值为2.


正确的做法:

据说80%学Python人,都会弄错的题

i因为闭包延迟绑定才会造成上面的问题,解决的办法就是给它立刻绑定,就搞定了 .


Python的学习道路上有很多好玩的有趣的风景,也有很多坑,欢迎大家一起讨论,如果你有问题,也欢迎来撩!


据说80%学Python人,都会弄错的题



扫码关注“菜鸟学Python”


推荐阅读:

帮你赚到第一桶金的Python代码

这8道Python面试题,你答不答的出来

太好玩了!用Python写个弹球游戏2.0

Python武功如何快速进阶

2017年度电影榜单出炉


本篇文章来源于: 菜鸟学Python

本文为原创文章,版权归所有,欢迎分享本文,转载请保留出处!

知行编程网
知行编程网 关注:1    粉丝:1
这个人很懒,什么都没写

发表评论

表情 格式 链接 私密 签到
扫一扫二维码分享