Python 初学者常犯的 5 个错误
原文发表于pythoncircle.com
在 Python 编程的初期,我们每个人都会遇到各种各样的奇怪 bug,在 Stack Overflow 上花费数小时苦苦寻找答案后,最终发现这并非 bug,而是 Python 的特性。这就是 Python 的运作方式。以下列出了 Python 初学者最常犯的 5 个错误。让我们来了解一下这些错误,这样就能省去在 Facebook 页面和群组里提问的几个小时。
- 创建字典或列表的副本。
当你需要复制字典或列表时,不要直接使用赋值运算符。
错误的:
>>> dict_a = {"name": "John", "address":"221B Baker street"}
>>> dict_b = dict_a
现在,如果您编辑/更新dict_b,dict_a也会更新,因为通过使用赋值运算符,您试图表明dict_b将指向与dict_a指向的对象相同的对象。
>>> dict_b["age"] = 26
>>> dict_b
{'address': '221B Baker street', 'name': 'John', 'age': 26}
>>> dict_a
{'address': '221B Baker street', 'name': 'John', 'age': 26}
>>>
正确的:
使用copy()ordeepcopy()方法。
>>> 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}
>>> dict_a
{'address': '221B Baker street', 'name': 'John', 'age': 26}
>>>
- 字典键。
假设我们将以下值放入一个字典中。
>>> dict_a = dict()
>>> dict_a
{}
>>> dict_a[1] = "apple"
>>> dict_a[True] = "mango"
>>> dict_a[2] = "melon"
如果我们尝试打印这个字典,输出结果会是什么?让我们看看。
>>> dict_a
{1: 'mango', 2: 'melon'}
刚才发生了什么?键在哪里True?
记住,布尔类是整数类的子类。整数中True1 的等价值为 1,2 的等价值False为 0。因此,键 1 的值被覆盖了。
>>> isinstance(True, int)
True
>>> isinstance(False, int)
True
>>> True == 1
True
>>> False == 0
True
>>>
- 更新列表或字典。
假设你想向列表中添加一个项目。
>>> list_a = [1,2,3,4,5]
>>> list_a = list_a.append(6)
>>> list_a
>>> # prints nothing
尝试更新字典。
>>> dict_a = {"a" : "b"}
>>> dict_a = dict_a.update({"c" : "d"})
>>> dict_a
>>> # prints nothing
好的,我们来尝试对列表进行排序。
>>> list_b = [2,5,3,1,7]
>>> list_b = list_b.sort()
>>> list_b
>>> # prints nothing
为什么什么都没打印出来?我们做错了什么?
序列对象的大部分方法,如排序、更新、追加、添加等,都采用原地操作,避免不必要地创建单独的副本,从而提高性能。
不要尝试将此类方法的输出赋值给变量。
正道:
>>> list_a = [1,2,3,4,5]
>>> list_a.append(6)
>>> dict_a = {"a" : "b"}
>>> dict_a.update({"c" : "d"})
>>> dict_a
{'c': 'd', 'a': 'b'}
>>> list_a.sort()
>>> list_a
[1, 2, 3, 4, 5, 6]
- 字符串驻留。
在某些情况下,Python 会尝试重用现有的不可变对象。字符串驻留就是其中一种情况。
>>> a = "gmail"
>>> b = "gmail"
>>> a is b
True
这里我们尝试创建两个不同的字符串对象。但是,当检查这两个对象是否相同时,返回了 True。这是因为 Python 没有创建新对象,b而是指向了b第一个值“gmail”。
长度为 1 的所有字符串都会被内部存储。除了 ASCII 字符、数字和下划线之外的任何字符都不会被内部存储。
让我们来看看。
>>> a = "@gmail"
>>> b = "@gmail"
>>> a is b
False
>>>
另外,请记住`if` 运算==符与 `if` 运算符不同is。`if`==检查值是否相等,而is`if` 检查两个变量是否指向同一个对象。
>>> a = "@gmail"
>>> b = "@gmail"
>>> a is b
False
>>> a == b
True
>>>
==因此,在使用不可变字符串或运算符时,请记住上述要点is。
- 默认参数只计算一次。
请看下面的例子。
def func(a, lst=[]):
lst.append(a)
return lst
print(func(1))
print(func(2))
你认为以上两条打印语句的输出结果会是什么?
我们来试运行一下。
>>> def func(a, lst=[]):
... lst.append(a)
... return lst
...
>>> print(func(1))
[1]
>>> print(func(2))
[1, 2]
>>>
为什么输出结果是[1,2]第二种情况?不应该是[2]?
关键在于,函数的默认参数只会被计算一次。第一次调用时func(1),列表lst会被计算,发现为空,因此会向列表中添加一个元素 1。但第二次调用时,列表已经有一个元素了,所以输出是 [1,2]。
额外提示:空格和制表符不要混用。千万别混用。你会哭的。
更多内容请访问pythoncircle.com:
- 将 robots.txt 文件添加到 Django 应用程序
- 如何免费在 Pythonanywhere 上托管 Django 应用
- 如何使用 Python 和 Django 以及 Office 365 发送电子邮件