菜鸟独白
Python语言虽然优美,简洁和强大,但是也有很多坑,一不小心就会掉进去。我学Python的时候也遇到过,今天总结一下,希望对大家能有收获!
1.陷阱1:可变默认参数
Python里面可变参数非常灵活,但是也有陷阱,不信你看看这个小例子:
我们希望每次调用这个函数的,因为第二个参数是默认参数,如果不提供第二个参数,就会创建一个新的列表,然后返回列表,大家猜猜看结果应该是多少:
是不是应该为[1][2][3].
但是实际上结果为:
[1, 2, 3]
[1, 2, 3]
[1, 2, 3]
也就是说变量地址l1,l2被l3污染了,为啥呢:
当函数被第一次调用的时候,这个默认的res列表就被创建了,这个列表的地址空间就生成了!关键来了,Python的默认参数就被创建 一次,而不是每次调用函数的时候创建。也就是说,后面的代码对这个列表的改变,会前面的内容也同样修改!
不信的话,可以把res的地址打印出来看看:
是不是地址都是一样的。
正确的做法:在每次函数调用时候,好的做法是把默认参数赋值为None来创建一个新的对象。
高级进阶:爬虫递归的使用
有的同学说这确实是个陷阱,但是好像没有什么实际的用途,我们看一个爬虫额例子,前几周我刚在小密圈里面搞了一个爬虫的实战活动,里面就一个需要循环爬取,递归调用的场景!
我解析一个网页的页面,获得解析的结果,如果当前的页数超过了最大页数,则停止,否则继续递归解析下一页.推荐给大家一个学习交流的地方,719+139+688,喜欢Python的一起high起来。
这里就用了res=None,递归还是蛮有用的。
2.陷阱2:闭包中延迟绑定
如果说上面的陷阱1还比较好理解,那下面的这个陷阱是就更有的迷惑性!大部分人都会掉进去,这就是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里面一个比较难理解的概念,经常和函数装饰器搞在一起,再加上一个匿名函数,头都昏了!我们来换一下普通函数方式来理解:
Python的闭包是延迟绑定,也就是说闭包中用到的变量的值,是在内部函数被调用的时候才查询得到的。
res里面包含了闭包函数make_square,这个闭包比较牛逼,它会对延伸到函数的作用域外边,也就是包含了对变量i的绑定,最后一次查询i的值为2.
正确的做法:
i因为闭包延迟绑定才会造成上面的问题,解决的办法就是给它立刻绑定,就搞定了 .
Python的学习道路上有很多好玩的有趣的风景,也有很多坑,欢迎大家一起讨论,如果你有问题,也欢迎来撩!
文章来源网络和自己整理,如有侵权,请联系24小时删除