听说这是70%学Python人,都会弄错的题,看你是否学到位

·  阅读 62
原文链接: click.aliyun.com

菜鸟独白

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

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

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

听说这是70%学Python人,都会弄错的题,看你是否学到位

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

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

但是实际上结果为:

[1, 2, 3]

[1, 2, 3]

[1, 2, 3]

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

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

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

听说这是70%学Python人,都会弄错的题,看你是否学到位

是不是地址都是一样的。

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

听说这是70%学Python人,都会弄错的题,看你是否学到位

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

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

我解析一个网页的页面,获得解析的结果,如果当前的页数超过了最大页数,则停止,否则继续递归解析下一页.推荐给大家一个学习交流的地方,719+139+688,喜欢Python的一起high起来。

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

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

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

听说这是70%学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里面一个比较难理解的概念,经常和函数装饰器搞在一起,再加上一个匿名函数,头都昏了!我们来换一下普通函数方式来理解:

听说这是70%学Python人,都会弄错的题,看你是否学到位

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

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

正确的做法:

听说这是70%学Python人,都会弄错的题,看你是否学到位

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

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

文章来源网络和自己整理,如有侵权,请联系24小时删除