”Python容易“似乎已经成了很多开发者的共识,的确,它的表达方式已经非常接近自然语言。不用像C++那样去考虑指针、内存,也不用像Java那样深入理解JVM。
慢慢的,开发者开始确切的认为”我们写的代码是完全正确的“。
但是,在忽视Python的细节的过程中,会发现,会出现奇奇怪怪的错误。回头定位时,迟迟定位不出问题,在网络上搜索也找不到对应的解决方案,回头看代码,觉得代码无懈可击。殊不知,在开发过程中已经犯了很多错误。
本文,就总结5个Python初学者经常会遇到的错误。不瞒各位,其中有些错误我当初也踩过坑,并且迟迟无法逃脱,希望把这些问题总结出来,避免大家再次踩坑!
1. 字典拷贝
有些场景下,需要对字典拷贝一个副本。这个副本用于保存原始数据,然后原来的字典去参与其他运算,或者作为参数传递给一些函数。
例如,
>>> dict_a = {"name": "John", "address":"221B Baker street"}
>>> dict_b = dict_a
利用赋值运算法把dict_a赋值给dict_b之后,这2个变量的值是相同的。
你或许会拿着dict_b去参与其他的运算,例如,更新/添加键值对。
但事实却不是你认为的那样,如果你更新或者编辑dict_b,dict_a也会随之改变,详细内容可以了解一下Python可变对象与不可变对象。
下面来看一下效果:
>>> dict_b["age"] = 26
>>> dict_b
{'address': '221B Baker street', 'name': 'John', 'age': 26}
>>> dict_a
{'address': '221B Baker street', 'name': 'John', 'age': 26}
你会发现,给dict_b添加了一个age:26键值对,dict_a也更新了,这样,我们留一个副本就没有任何意义了。
针对这个问题,可以用Python中的浅拷贝copy、深拷贝deepcopy来解决,下面来看一下,
>>> dict_c = dict_b.copy()
>>> dict_c["location"] = "somewhere"
>>> dict_c
{'address': '221B Baker street', 'name': 'John', 'age': 26, 'location': 'somewhere'}
>>> dict_b
{'address': '221B Baker street', 'name': 'John', 'age': 26}
2. 字典键值
首先,来看一个示例,
>>> dict_a = dict()
>>> dict_a
{}
>>> dict_a[1] = "apple"
>>> dict_a[True] = "mango"
>>> dict_a[2] = "melon"
>>> dict_a
{1: 'mango', 2: 'melon'}
你注意到发生了什么吗?
输出字典之后,发现键值True没有了!
这是因为,在Python中,True相当于1、False相当于0,因此,在dict_a[True] = "mango"这行代码里,它把原来键值为1给替换了。
可以来验证一下True相当于1的说法:
>>> isinstance(True, int)
True
>>> True == 1
True
3. 更新列表或字典
同样,先看一个列表的示例:
>>> list_a = [1,2,3,4,5]
>>> list_a = list_a.append(6)
>>> list_a
# 不输出任何内容
再看一个字典的示例:
>>> dict_a = {"a" : "b"}
>>> dict_a = dict_a.update({"c" : "d"})
>>> dict_a
# 不输出任何内容
发现,打印list_a和dict_a竟然没有任何内容输出!
这是因为,在Python中列表、字典中的一些方法,如排序、更新、附加、添加等,不会创建不必要的副本,从而提升性能,因此,不需要重新分配给变量。
再看一下正确的方法:
>>> list_a = [1,2,3,4,5]
>>> list_a.append(6)
>>> list_a.sort()
>>> list_a
[1, 2, 3, 4, 5, 6]
4. 驻留字符串
在某些情况下,Python尝试重用现有的不可变对象。字符串驻留就是这样一种情况。
来看一个示例对比,
>>> a = "gmail"
>>> b = "gmail"
>>> a is b
True
然后修改一下,
>>> a = "@gmail"
>>> b = "@gmail"
>>> a is b
False
是不是很神奇?我们只加了一个@符号,结果却截然不同!
在第一个实现方法中,尝试创建两个不同的字符串对象。但是当检查两个对象是否相同时,它返回True。
这是因为python并没有创建另一个对象b,而是将b指向了第一个值gmail,换句话说它被驻留了。
但是,如果字符串中除ASCII字符、数字、下划线以外的其他字符时,它则不会驻留,这样的话,它就不会再指向@gmail。
这里需要注意一下,is与==的运算是不同的。
==用于判断值是否相等,is不仅需要值相等,还需要指向同一个对象。
>>> a = "@gmail"
>>> b = "@gmail"
>>> a is b
False
>>> a == b
True
5. 默认参数只计算一次
先看一下下面这个示例:
>>> def func(a, lst=[]):
... lst.append(a)
... return lst
...
>>> print(func(1))
[1]
>>> print(func(2))
[1, 2]
这里发生了什么?
我在func中给了一个默认参数[],然后先后调用2次func函数。
按照我们常规的认识,这2次调用是分开的,第1次调用输出[1],第二次应该输出[2],为什么第2次调用时列表里竟然还保留着第1次调用时的值?
这是因为,在Python中,默认参数只会被计算一次。第1次调用func(1)时,它用到了默认参数。但是,第2次调用就不会再去计算默认参数,直接在[1]的基础上附加一个值。
结语
本文介绍的这些经常犯错的点,或许你还没有遇到过,因此会觉得不以为然。但是,总会在某个时间点、开发某个小模块时不知不觉中用到这5个问题所涵盖的其中某个功能。
如果想当然,按照我们概念里认为的那样去做,结果可想而知,会出现错误。
因此,在Python开发过程中,应该注意一些细节,深入系统的学习一下Python,避免在一些Python基本特性方面犯一些错误。
如果你对Python有深入的了解,自然会避免这些错误。反之,则会给你带来大麻烦,一旦出了错误就很难定位出来。
关于Python技术储备
学好 Python 不论是就业还是做副业赚钱都不错,但要学会 Python 还是要有一个学习规划。最后大家分享一份全套的 Python 学习资料,给那些想学习 Python 的小伙伴们一点帮助!
一、Python所有方向的学习路线
Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。
二、Python必备开发工具
三、精品Python学习书籍
当我学到一定基础,有自己的理解能力的时候,会去阅读一些前辈整理的书籍或者手写的笔记资料,这些笔记详细记载了他们对一些技术点的理解,这些理解是比较独到,可以学到不一样的思路。
四、Python视频合集
观看零基础学习视频,看视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。
五、实战案例
光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。
六、Python练习题
检查学习结果。
七、面试资料
我们学习Python必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。