20个连熟练的Python程序员都会犯的新手错误 在Python中编码时应该避免的常见错误集合
编程(不仅仅是Python,还有任何编程语言)最好的一点是,通常有多种方法来实现同一个解决方案。
使用不同的方法来达到相同的输出
当然,有些方法比其他方法更好,这可能是由于各种原因,比如。
内存占用少 运行时间高效 更少的代码行数 容易理解 逻辑简单,等等。
在这篇文章中,我将向你介绍20种具体的情况,在这些情况下,Python程序员会不自觉地落入编写大量的、不优雅的、复杂的Python代码的陷阱--这最终使他们无法释放出Python的真正潜力。
与此同时,我还将为所提出的问题提供另一种解决方案,以协助你纠正这些失误。
你可以在这里找到这篇文章的代码。
让我们开始吧 !
#1 使用多个打印语句 天真的方法 如果你想打印多个变量,那么天真的方法表明,每个变量都应该有自己的print()
语句。
a, b, c = 10, 5, 3
print(a)
print(b)
print(c)
10
5
3
优雅的方法
根据我的经验,使用多个打印语句通常是编码者(尤其是新手)在用Python编码时最常见的错误。
然而,他们不知道的是,通过print(),你可以在一个打印语句中打印多个变量,如下所示。
a, b, c = 10, 5, 3
print(a, b, c, sep = "\n")
10
5
3
上面的sep参数指定了使用同一个打印语句打印的各种变量之间的分隔符(上面的a、b和c)
a, b, c = 10, 5, 3
print(a, end = "\n---\n")
print(b, end = "\n---\n")
print(c)
10
---
5
---
3
注意,end参数用于指定打印语句的结束符。
在上面的代码中,end='\n----\n'参数打印新行字符,后面是----,进一步是新行字符。
#2 使用FOR循环打印同一变量 天真的方法 如标题所示,目的是多次打印同一个变量。
repeat = 10
a = "ABC"
for _ in range(repeat):
print(a, end = "")
ABCABCABCABCABCABCABCABCABCABC
当然,你应该创建一个FOR循环,并迭代你想打印的变量的次数,对吗?我的意思是,这有什么错呢?
优雅的方法
repeat = 10
a = "ABC"
print(a*repeat)
ABCABCABCABCABCABCABCABCABCABC
虽然写一个FOR循环没有什么坏处,而且一切都很好,但是没有必要写一个FOR循环来多次打印同一个变量。
#3-4 创建一个单独的变量来跟踪循环中的索引
天真的方法 - 1 为了实现这一点,通常会定义一个新的变量(idx)来跟踪索引值,并在每次迭代时将其递增,如下所示。
idx = 0
char_list = ["a", "b", "c", "d", "e", "f"]
for i in char_list:
print("index =", idx, "value =", i, sep = " ")
idx += 1
index = 0 value = a
index = 1 value = b
index = 2 value = c
index = 3 value = d
index = 4 value = e
index = 5 value = f
天真的方法 - 2 如果不是上述方法,人们会创建一个范围迭代器来跟踪索引,如下面的代码所示。
char_list = ["a", "b", "c", "d", "e", "f"]
for idx in range(len(char_list)):
print("index =", idx, "value =", char_list[idx], sep = " ")
idx += 1
index = 0 value = a
index = 1 value = b
index = 2 value = c
index = 3 value = d
index = 4 value = e
index = 5 value = f
优雅的方法 感谢开发enumerate()方法的开发者。
char_list = ["a", "b", "c", "d", "e", "f"]
for idx, i in enumerate(char_list):
print("index =", idx, "value =", i, sep = " ")
index = 0 value = a
index = 1 value = b
index = 2 value = c
index = 3 value = d
index = 4 value = e
index = 5 value = f
从本质上讲,使用这个方法,你可以同时跟踪索引(idx)和值(i),如下所示。
#5 使用FOR循环将一个列表转换为一个字符串
列表到字符串 简单的方法
使用FOR循环,如下图所示,我们可以一次收集一个列表的元素。
char_list = ["A", "B", "C", "D", "E"]
final_str = ""
for i in char_list:
final_str += i
print(final_str)
ABCDE
优雅的方法 将一个列表转换为字符串的时尚方法是使用 join() 方法,如下图所示。
char_list = ["A", "B", "C", "D", "E"]
final_str = "".join(char_list)
print(final_str)
ABCDE
这不仅可以使你免于写一些不必要的长代码,而且也和for-loop的方法一样直观。
#6 使用 FOR 循环从一个列表中删除重复的内容
从一个列表中删除重复的内容 天真烂漫的方法
char_list = ["A", "B", "A", "D", "C", "B", "E"]
final_list = []
for i in char_list:
if i not in final_list:
final_list.append(i)
print(final_list)
['A', 'B', 'D', 'C', 'E']
FOR循环又一次拯救了我们!
天真的方法是对输入的列表进行迭代,并将唯一的元素存储在一个新的列表中。
优雅的方法
然而,从一个列表中删除重复的元素只需要一行Python代码就可以了,如下图所示。
char_list = ["A", "B", "A", "D", "C", "B", "E"]
set(list(char_list))
{'A', 'B', 'C', 'D', 'E'}
上面返回的是一个集合,你可以通过以下方式获得一个列表。
#7 使用 FOR 循环在列表中搜索一个元素
天真的方法
假设你想知道一个元素是否存在于一个列表(或集合)中,并返回一个布尔响应(如果它存在则为真,否则为假)。
下面演示的是天真的方法。
char_list = ["A", "B", "A", "D", "C", "B", "E"]
search_char = "D"
found = False
for i in char_list:
if i == search_char:
found = True
break
print(found)
True
唉! 太多的代码了,不是吗?
优雅的方法 让我们用in关键字将其简化为一个单行的实现。
char_list = ["A", "B", "A", "D", "C", "B", "E"]
search_char = "D"
search_char in char_list
True
#8 使用一个索引变量在两个相同大小的迭代变量上进行迭代
天真的方法
与我们在第3-4节所做的类似,即为索引专门定义一个变量,这里的天真方法是在这里采用同样的方法,如下所示。
list1 = [1, 3, 6, 2, 5]
list2 = [0, 4, 1, 9, 7]
for idx in range(len(list1)):
print("value1 =", list1[idx], "value2 =", list2[idx], sep = " ")
value1 = 1 value2 = 0
value1 = 3 value2 = 4
value1 = 6 value2 = 1
value1 = 2 value2 = 9
value1 = 5 value2 = 7
高明的方法
精明的方法是使用zip()
函数,在两个迭代变量中配对相应的值。
list1 = [1, 3, 6, 2, 5]
list2 = [0, 4, 1, 9, 7]
for i, j in zip(list1, list2):
print("value1 =", i, "value2 =", j, sep = " ")
value1 = 1 value2 = 0
value1 = 3 value2 = 4
value1 = 6 value2 = 1
value1 = 2 value2 = 9
value1 = 5 value2 = 7
#9 使用FOR循环反转一个列表
反转列表 天真的方法
input_list = [1, 2, 3, 4, 5]
output_list = []
for idx in range(len(input_list), 0, -1):
output_list.append(input_list[idx-1])
print(output_list)
[5, 4, 3, 2, 1]
你可能已经猜到了,我们可以反向迭代列表并将元素追加到一个新的列表中,如下图所示。
优雅的方法
input_list = [1, 2, 3, 4, 5]
output_list = input_list[::-1]
print(output_list)
[5, 4, 3, 2, 1]
如果你了解 Python 中的分片,优雅的解决方案在这里只是一个简单的单行代码。没有 FOR 循环!
#10使用FOR循环检查Palindrome
简单的方法 根据上述情况(#9 - 反转一个列表),我们可以检查反转的列表是否与输入列表相同。
input_list = [1, 2, 3, 2, 1]
output_list = []
for idx in range(len(input_list), 0, -1):
output_list.append(input_list[idx-1])
print(output_list == input_list)
True
优雅的方法
input_list = [1, 2, 3, 2, 1]
output_list = input_list[::-1]
print(output_list == input_list)
True
如上所述,优雅的方法是使用切片法,并与输入列表进行比较。
#11 使用FOR循环计算一个元素在可迭代列表中的出现次数
天真方法
char_list = ["A", "B", "A", "D", "C", "B", "E"]
search_char = "B"
char_count = 0
for i in char_list:
if search_char == i:
char_count += 1
print(char_count)
2
找到一个元素的频率的天真方法是使用FOR循环遍历列表并计算出现的次数。
优雅的方法
在这种情况下,优雅的方法是使用count()方法,它使我们不用再写一个FOR循环(又一次)。
char_list = ["A", "B", "A", "D", "C", "B", "E"]
char_list.count("A")
2
你也可以在一个字符串输入上使用count()方法。
string = "ABADCBE"
string.count("A")
2
#12 使用FOR循环获得一个字符串的子串
简单的方法
这里的目标是返回一个长度为n_chars的子串,从start_index位置开始。
新手的方法是使用FOR循环来解决这个问题,如下所示。
input_str = "ABCDEFGHIJKL"
start_index = 4
n_chars = 5
output_str = ""
for i in range(n_chars):
output_str += input_str[i+start_index]
print(output_str)
EFGHI
优雅的方法
input_str = "ABCDEFGHIJKL"
start_index = 4
n_chars = 5
output_str = input_str[start_index:start_index+n_chars]
print(output_str)
EFGHI
然而,单行本的方法是使用分片,这样就可以省去写FOR循环。
#13 定义长整数常量
想象一下,你想声明一个数值为10²¹的整数变量。
天真的方法
x = 1000000000000000000000
True
理想情况下,人们会连续写零,并在打字时进行计数。
但如果说别人想参考这段代码。对他们来说,数所有的零不是很麻烦吗?
优雅的方法 为了提高可读性,你可以用_(下划线)分隔一组零,如下图所示。
x = 1_000_000_000_000_000_000_000
但这仍然是个麻烦,不是吗?为什么有人要计算零呢?
x = pow(10, 21)
如果数字可以用a^b的形式来表达,你应该用pow()方法来代替。
#14 用IF条件交换一个字符串的情况
给定一个字符串,目的是使大写字母变成小写字母,反之亦然。
天真方法 一个天真的方法是检查每个元素的大小写,然后为每个大小写设置具体条件。
input_str = "AbCDeFGhIjkl"
output_str = ""
for i in input_str:
if i.islower():
output_str += i.upper()
elif i.isupper():
output_str += i.lower()
else:
output_str += i
print(output_str)
aBcdEfgHiJKL
输出结果没有问题,但你为什么要这样做呢?
优雅的方法 用swapcase()
方法代替。
input_str = "AbCDeFGhIjkl"
output_str = input_str.swapcase()
print(output_str)
aBcdEfgHiJKL
#15 获得两个集合的联合
两个集合的并集 天真的方法
遍历两个集合,将元素添加到一个新的集合中。
set_a = {1, 2, 4, 8}
set_b = {3, 8, 7, 1, 9}
union_set = set()
for i in set_a:
union_set.add(i)
for i in set_b:
union_set.add(i)
print(union_set)
{1, 2, 3, 4, 7, 8, 9}
太多的代码行了,不是吗?
让我们把它减少到一行。
优雅的方法
Python中的集合数据结构提供了一个union()
方法来实现两个集合的联合。
set_a = {1, 2, 4, 8}
set_b = {3, 8, 7, 1, 9}
union_set = set_a.union(set_b)
print(union_set)
{1, 2, 3, 4, 7, 8, 9}
更重要的是,你可以把它扩展到任何数量的输入集。
set_a = {1, 2, 4, 8}
set_b = {3, 8, 7, 1, 9}
set_c = {5, 9, 10, 3, 2}
set_d = {7, 2, 13, 15, 0}
union_set = set_a.union(set_b, set_c, set_d)
print(union_set)
{0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 13, 15}
这不是很酷吗?想象一下,你要写多少个FOR循环来合并这四个集合。
#16 获得两个集合的交集
天真的方法
set_a = {1, 2, 4, 8}
set_b = {3, 8, 7, 1, 9}
intersection_set = set()
for i in set_a:
if i in set_b:
intersection_set.add(i)
print(intersection_set)
{8, 1}
与上面讨论的并集的情况类似,我们可以找到两个集合之间的共同元素,如下所示。
优雅的方法
set_a = {1, 2, 4, 8}
set_b = {3, 8, 7, 1, 9}
intersection_set = set_a.intersection(set_b)
print(intersection_set)
{8, 1}
然而,你可以使用intersection()
方法来实现同样的效果。
#17 在IF语句中编写多个条件
为了详细说明这一点,假设你想实现以下逻辑。输入是一个整数a。
将输入映射到输出的函数 (图片由作者提供) 天真的方法 在这里,人们会使用多个OR分隔的条件语句来实现上述逻辑。
优雅的方法 一个聪明的方法是通过使用in关键字来避免多个条件语句,如下图所示。
#18 改变一个列表中所有元素的数据类型
给定一个代表整数的字符串列表,目标是通过改变数据类型将其转换为整数列表。
简单的方法 使用 FOR 循环遍历该列表,并对各个元素进行类型转换。
a = 1
if a == 1 or a == 2 or a==3:
a += 1
elif a == 4 or a == 5 or a==6:
a += 5
else:
a *= 2
print(a)
2
优雅的方法
一个聪明的方法是使用map()
,如下图所示。
a = 1
if a in (1, 2, 3):
a += 1
elif a in (4, 5, 6):
a += 5
else:
a *= 2
print(a)
2
map()
方法的第一个参数是接受一个函数int
,第二个参数是一个可迭代的列表input_list
input_list = ["7", "2", "13", "15", "0"]
output_list = []
for idx, i in enumerate(input_list):
output_list.append(int(input_list[idx]))
print(output_list)
[7, 2, 13, 15, 0]
优雅的方法
input_list = ["7", "2", "13", "15", "0"]
output_list = list(map(int, input_list))
print(output_list)
[7, 2, 13, 15, 0]
#19 变量互换
给定两个变量,目标是将第一个变量中的值转移到第二个变量中,将第二个变量中的值转移到第一个变量中。
天真的方法 大多数 C/C++ 程序员在这里采取的方法是定义一个新的变量 (temp),他们通常也会在 Python 中这样做。
a = "123"
b = "abc"
temp = a
a = b
b = temp
print(a, b)
abc 123
优雅的方法
a = "123"
b = "abc"
a, b = b, a
print(a, b)
abc 123
幸运的是,Python允许在一条语句中进行多次赋值,从而消除了对任何临时变量的需求。
#20 使用嵌套循环生成两个列表的所有组合
给出两个列表(a的长度为n,b的长度为m),生成所有nxm的组合。
简单的方法 写两个嵌套的FOR循环,并将所有的组合附加到一个列表中。
list1 = ["A", "B", "C"]
list2 = [1, 2]
combinations = []
for i in list1:
for j in list2:
combinations.append([i, j])
print(combinations)
[['A', 1], ['A', 2], ['B', 1], ['B', 2], ['C', 1], ['C', 2]]
优雅的方法
from itertools import product
list1 = ["A", "B", "C"]
list2 = [1, 2]
combinations = list(product(list1, list2))
print(combinations)
[('A', 1), ('A', 2), ('B', 1), ('B', 2), ('C', 1), ('C', 2)]
优雅的方法是使用itertools
库中的product()
方法,如下图所示。
结论 最后,在这篇文章中,我演示了20种不同的情况,我相信大多数Python程序员都经历过这些情况,并且可能采取了错误的编码解决方案。
如果你注意到,在大多数情况下,优雅的方法主要集中在消除前一种方法中使用的FOR循环的明确编码。
本文由 mdnice 多平台发布