关于python:相见恨晚Python那些不为人知的大坑

7次阅读

共计 2771 个字符,预计需要花费 7 分钟才能阅读完成。

”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_bdict_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_adict_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 编程学习圈,每日干货分享,发送“J”还可支付大量学习材料,内容笼罩 Python 电子书、教程、数据库编程、Django,爬虫,云计算等等。或是返回编程学习网,理解更多编程技术常识。

正文完
 0