陷阱21:不要使用and
和or
运算符来判断布尔值
- 布尔值是Python中的一种基本的数据类型,它可以表示真或假,它的字面值只有两个,
True
和False
。 - 有时候,我们需要判断一个表达式的真假,比如判断一个条件是否满足,或者一个逻辑是否成立,就需要使用
and
和or
运算符来连接多个表达式,形成一个复合的表达式。 - 但是,如果我们使用
and
和or
运算符来判断布尔值,就可能导致一些意想不到的结果,甚至引发错误。
错误的代码
# 定义一个函数,用于判断一个数是否是偶数
def is_even(x):
return x % 2 == 0 # 使用%运算符来计算余数,如果余数是0,就返回True,否则返回False
# 调用函数,期望得到 True
print(is_even(2)) # True
# 调用函数,期望得到 False
print(is_even(3)) # False
# 使用and运算符来判断两个数是否都是偶数,期望得到 True
print(is_even(2) and is_even(4)) # 4
# 使用or运算符来判断两个数是否至少有一个是偶数,期望得到 True
print(is_even(2) or is_even(3)) # True
为什么会出错呢?
- 因为使用
and
和or
运算符来判断布尔值,会返回其中一个操作数的值,而不是一个布尔值,这就意味着,如果我们打印或赋值这个表达式的值,就会得到一个非布尔值,而不是一个布尔值。 - 这就导致了我们无法正确地判断一个表达式的真假,而是得到一个无意义或者错误的值。
and
运算符的返回规则是,如果第一个操作数是False
,就返回第一个操作数的值,否则返回第二个操作数的值。or
运算符的返回规则是,如果第一个操作数是True
,就返回第一个操作数的值,否则返回第二个操作数的值。
正确的代码
# 定义一个函数,用于判断一个数是否是偶数
def is_even(x):
return x % 2 == 0 # 使用%运算符来计算余数,如果余数是0,就返回True,否则返回False
# 调用函数,期望得到 True
print(is_even(2)) # True
# 调用函数,期望得到 False
print(is_even(3)) # False
# 使用and运算符来判断两个数是否都是偶数,期望得到 True
print(is_even(2) and is_even(4)) # True
# 使用or运算符来判断两个数是否至少有一个是偶数,期望得到 True
print(is_even(2) or is_even(3)) # True
陷阱22:不要使用for
循环来遍历字典
- 字典是Python中的一种数据结构,它可以存储键值对,也就是一组由一个唯一的键和一个对应的值组成的数据,它的字面值用花括号
{}
来表示,比如{"name": "Alice", "age": 18}
。 - 有时候,我们需要遍历字典中的键值对,比如打印或修改它们的值,就需要使用
for
循环来遍历字典。 - 但是,如果我们使用
for
循环来遍历字典,就可能导致一些意想不到的结果,甚至引发错误。
错误的代码
# 定义一个字典,它的键是学生的姓名,值是学生的成绩
scores = {"Alice": 90, "Bob": 80, "Charlie": 70, "David": 60}
# 使用for循环来遍历字典,期望得到每个学生的姓名和成绩
for x in scores:
print(x, scores[x]) # 打印键和值
为什么会出错呢?
- 因为使用
for
循环来遍历字典,会默认遍历字典的键,而不是键值对,这就意味着,如果我们想要得到字典的值,就需要再用键来索引字典,这就会增加代码的复杂度和冗余性,降低代码的可读性和效率。 - 如果字典的键不是字符串或者数字,而是其他的可变或者不可哈希的类型,比如列表或者字典,就会导致无法用键来索引字典,引发类型错误或者键错误。
正确的代码
# 定义一个字典,它的键是学生的姓名,值是学生的成绩
scores = {"Alice": 90, "Bob": 80, "Charlie": 70, "David": 60}
# 使用for循环和items方法来遍历字典,得到每个学生的姓名和成绩
for name, score in scores.items():
print(name, score) # 打印键和值
陷阱23:不要使用str.join
方法来连接列表中的元素
- 列表是Python中最常用的数据结构之一,它可以存储任意类型的元素,并且可以动态地增加或删除元素。
- 有时候,我们需要将列表中的元素连接成一个字符串,比如打印或格式化它们的值,就需要使用
str.join
方法或+
运算符来连接列表中的元素。 - 但是,如果我们使用
str.join
方法来连接列表中的元素,就可能导致一些意想不到的结果,甚至引发错误。
错误的代码
# 定义一个列表,它的元素都是数字
lst = [1, 2, 3, 4, 5, 6]
# 使用str.join方法来连接列表中的元素,期望得到 "1, 2, 3, 4, 5, 6"
print(", ".join(lst)) # TypeError: sequence item 0: expected str instance, int found
为什么会出错呢?
- 因为使用
str.join
方法来连接列表中的元素,会要求列表中的元素都是字符串类型,而不是其他的类型,这就意味着,如果我们想要连接列表中的非字符串元素,就需要先将它们转换成字符串,然后再用str.join
方法来连接,这就会增加代码的复杂度和冗余性,降低代码的可读性和效率。 - 如果列表中的元素不是字符串类型,而是其他的类型,比如数字或者列表,就会导致无法用
str.join
方法来连接,引发类型错误。
正确的代码
# 定义一个列表,它的元素都是数字
lst = [1, 2, 3, 4, 5, 6]
# 使用列表推导式和str函数来将列表中的元素转换成字符串,然后使用str.join方法来连接列表中的元素,期望得到 "1, 2, 3, 4, 5, 6"
print(", ".join([str(x) for x in lst])) # 1, 2, 3, 4, 5, 6
陷阱24:不要使用list.append
方法来添加元素到集合
- 集合是Python中的一种数据结构,它可以存储不重复的元素,并且可以进行集合运算,比如交集、并集、差集等,它的字面值用花括号
{}
来表示,比如{1, 2, 3}
。 - 有时候,我们需要向集合中添加元素,比如去除重复的元素,或者扩展集合的范围,就需要使用
set.add
方法或set.update
方法来添加元素到集合。 - 但是,如果我们使用
list.append
方法来添加元素到集合,就可能导致一些意想不到的结果,甚至引发错误。
错误的代码
# 定义一个集合,它的元素都是数字
s = {1, 2, 3, 4, 5}
# 使用list.append方法来向集合中添加元素,期望得到 {1, 2, 3, 4, 5, 6}
s.append(6) # AttributeError: 'set' object has no attribute 'append'
为什么会出错呢?
- 因为使用
list.append
方法来添加元素到集合,会引发属性错误,因为集合对象没有append
这个属性,这个方法只适用于列表对象,而不是集合对象,这就意味着,如果我们想要向集合中添加元素,就不能使用list.append
方法,而要使用set.add
方法或set.update
方法,这两个方法是集合对象的属性,专门用于向集合中添加元素。
正确的代码
# 定义一个集合,它的元素都是数字
s = {1, 2, 3, 4, 5}
# 使用set.add方法来向集合中添加单个元素,期望得到 {1, 2, 3, 4, 5, 6}
s.add(6)
print(s) # {1, 2, 3, 4, 5, 6}
# 使用set.update方法来向集合中添加多个元素,期望得到 {1, 2, 3, 4, 5, 6, 7, 8, 9}
s.update([7, 8, 9])
print(s) # {1, 2, 3, 4, 5, 6, 7, 8, 9}
陷阱25:不要使用dict.keys
方法来判断一个键是否在字典中
- 字典是Python中的一种数据结构,它可以存储键值对,也就是一组由一个唯一的键和一个对应的值组成的数据,它的字面值用花括号
{}
来表示,比如{"name": "Alice", "age": 18}
。 - 有时候,我们需要判断一个键是否在字典中,比如根据键来获取或修改值,就需要使用
in
运算符或dict.get
方法或dict.setdefault
方法来判断一个键是否在字典中。 - 但是,如果我们使用
dict.keys
方法来判断一个键是否在字典中,就可能导致一些意想不到的结果,甚至引发错误。
错误的代码
# 定义一个字典,它的键是学生的姓名,值是学生的成绩
scores = {"Alice": 90, "Bob": 80, "Charlie": 70, "David": 60}
# 使用dict.keys方法来判断"Alice"是否在字典中,期望得到 True
print("Alice" in scores.keys()) # True
# 使用dict.keys方法来判断"Emma"是否在字典中,期望得到 False
print("Emma" in scores.keys()) # False
# 使用dict.keys方法来判断"Bob"是否在字典中,期望得到 True
print("Bob" in scores.keys()) # True
为什么会出错呢?
- 因为使用
dict.keys
方法来判断一个键是否在字典中,会返回一个列表,而不是一个布尔值,这就意味着,如果我们想要得到一个布尔值,就需要再用in
运算符来判断键是否在列表中,这就会增加代码的复杂度和冗余性,降低代码的可读性和效率。 - 如果字典的键不是字符串或者数字,而是其他的可变或者不可哈希的类型,比如列表或者字典,就会导致无法用
in
运算符来判断键是否在列表中,引发类型错误或者键错误。
正确的代码
# 定义一个字典,它的键是学生的姓名,值是学生的成绩
scores = {"Alice": 90, "Bob": 80, "Charlie": 70, "David": 60}
# 使用in运算符来判断"Alice"是否在字典中,返回一个布尔值,期望得到 True
print("Alice" in scores) # True
# 使用in运算符来判断"Emma"是否在字典中,返回一个布尔值,期望得到 False
print("Emma" in scores) # False
# 使用in运算符来判断"Bob"是否在字典中,返回一个布尔值,期望得到 True
print("Bob" in scores) # True