Python老手也会犯的20个新手级错误

news2024/11/23 16:55:05

Python编码时应避免的常见错误

 

编程(不仅Python,也包括其它编程语言)最好的一点是,有多种方法来实现同一解决方案。

使用不同的方法来达到相同的结果(图像由作者绘制)

使用不同的方法来达到相同的结果(图像由作者绘制)

由于下述原因,有些方法会比其他方法更好:

  1. 消耗更少的内存
  2. 运行效率
  3. 较少的代码
  4. 更容易理解
  5. 逻辑简单

在这篇文章中,我将向你介绍20种场景,这些场景都会让开发者不知不觉的陷入臃肿,丑陋,复杂的Python编码陷阱中,从而限制发挥Python的潜力。

除此之外,我还会针对每个错误提供一个替代方案进行解决。

点击这里查看本文的代码

开始吧!

1 多次使用打印语句

新手写法

如果你想打印多个变量,简单的方式是为每个变量都使用 print 语句。

a, b, c = 10, 5, 3  

print(a)  

print(b)  

print(c)  

优雅的写法

根据经验,使用多个 print 语句通常是编程人员(特别是新手)在 Python 中编码时最常犯的错误,因为他们不知道使用 print 语句,可以在一行代码中打印多个变量,代码如下:

a, b, c = 10, 5, 3  

print(a, b, c, sep = "\n")  

上述 sep 参数用于指定 print 语句输出各个变量值(a,b,c)之间的分隔符。

注意:end 参数用于设置 print 语句输出内容的结尾字符。

a, b, c = 10, 5, 3  



print(a, end = "\n---\n")  

print(b, end = "\n---\n")  

print(c)  

上述代码中,参数 end=”\n---\n” 用于当输出一行后,输出 ---,然后在输出新一行字符。

2 使用FOR 循环打印相同的变量

新手写法

如题所示,你的目标是多次打印相同的变量,所以你会创建一个 FOR 循环并迭代预期打印次数,对吗?我的意思是,这有什么问题吗?

repeat = 10  

a = "ABC"  

for _ in range(repeat):  

print(a, end = "")  

优雅的写法

虽然编写一个FOR循环没有坏处,并且一切正常,但是没有必要编写一个 FOR 循环来多次打印同一变量。

repeat = 10  

a = "ABC"  

print(a*repeat)  

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  

新手的写法2

如果不使用上述方法,人们还会创建一个 range 迭代器来跟踪索引,代码如下:

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  

优雅的写法

感谢设计了 enumerate() 函数的开发人员,使用这种方法可以按照下述方式跟踪索引(idx)和值(i)。

char_list = ["a", "b", "c", "d", "e", "f"]  

for idx, i in enumerate(char_list):  

print("index =", idx, "value =", i, sep = " ")  

5 使用FOR循环将列表转换为字符串

 

字符串的列表(图像由作者绘制)

新手写法

如下所示,使用 FOR 循环每次收集一个元素

char_list = ["A", "B", "C", "D", "E"]  

final_str = ""  

for i in char_list:  

final_str += i  

print(final_str)  

优雅的写法

将列表转换为字符串的优雅方法是使用 join() 方法,如下所示:

char_list = ["A", "B", "C", "D", "E"]  

final_str = "".join(char_list)  



print(final_str)

上述代码不仅可以避免编写一些不必要的长代码,而且与 FOR 循环方法一样直观。

6 使用 FOR 循环从列表中删除重复项

新手写法

 

从列表中删除重复项(图像由作者绘制)

再次使用 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)

优雅的写法

只需要一行 Python 代码就可以从列表中删除重复内容,如下所示:

char_list = ["A", "B", "A", "D", "C", "B", "E"]  

set(list(char_list)) 

上面的代码返回一个集合,你可以将其转换为列表:

char_list = ["A", "B", "A", "D", "C", "B", "E"]  

list(set(list(char_list))) 

7 使用 FOR 循环在列表中检索元素

新手写法

如果你想知道某个元素是否存在于列表(或集合)中,并返回一个布尔值(如果存在则为 True,否则为 False),新手实现如下所示:

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) 

代码有点多,是吧?

优雅的写法

通过关键字in 可以使用一行代码实现。

char_list = ["A", "B", "A", "D", "C", "B", "E"]  

search_char = "D"  

search_char in char_list  

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 = " ")  

优雅的写法

有经验的方法是使用 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 = " ")  

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)  

优雅的写法

如果你了解 Python 中的切片,那优秀的解决方案只需要一行代码。

input_list  = [1, 2, 3, 4, 5]  

output_list = input_list[::-1]  

print(output_list)  

不需要 FOR 循环!

10使用 FOR 循环检查回文结构

新手写法

在扩展了上述情况(#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)  

优雅的写法

正如前文讨论的那样,有经验的方式是使用切片,并将结果与原列表进行比较。

input_list  = [1, 2, 3, 2, 1]  


output_list = input_list[::-1]  

print(output_list == input_list)  

11使用 FOR 循环计算迭代对象中元素的出现次数

新手写法

查找元素频率的简单方法是使用 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)  

优雅的写法

在这种情况下,避免编写 FOR 循环的有经验写法是使用 count() 方法。

char_list = ["A", "B", "A", "D", "C", "B", "E"]  

char_list.count("A")  

也可以对字符串变量使用 count() 方法。

string = "ABADCBE"  

string.count("A")  

12使用 FOR 循环获取字符串的子串

新手写法

本次目标是从 start_index 位置开始,返回一个长度为 n_chars 的字符串子串。

新手解决这个问题的方法是使用 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)  

优雅的写法

使用切片,可以避免 FOR 循环。

input_str = "ABCDEFGHIJKL"  

start_index = 4  

n_chars = 5  

output_str = input_str[start_index:start_index+n_chars]  

print(output_str) 

13 定义长整数常量

假设你想声明一个值为1021的整数变量。

新手写法

x = 1000000000000000000000 

理想情况下,人们会连续写0,并在打字时进行计数,但如果有人想引用这个代码,他们数0难道不会很麻烦吗?

优雅的写法

为了提高可读性,可以用 _(下划线)分隔一组0,如下所示:

x = 1_000_000_000_000_000_000_000

但这仍然是一个麻烦,为什么数 0?

如果数字可以表示为 a^b 形式,那应该使用 pow() 方法。

x = pow(10, 21)

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)  

输出没有问题,但为什么要这么做?

优雅的写法

使用  swapcase ()方法。

input_str = "AbCDeFGhIjkl"  

output_str = input_str.swapcase()  


print(output_str)  

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)  

代码太多了,不是吗?让我们把它精简到一行。

优雅的写法

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)  

更重要的是,你可以将其扩展到任意数量的输入集合。

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) 

这很酷吧? 想象一下,要合并4个集合,需要编写多少个 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)  

优雅的写法

你可以使用 intersection() 方法实现同样的功能:

set_a = {1, 2, 4, 8}  

set_b = {3, 8, 7, 1, 9}  

intersection_set = set_a.intersection(set_b)  


print(intersection_set) 

17在 IF 语句中写多个条件

为了详细说明这一点,假设你想实现如下逻辑。

 

函数将输入映射到输出(图像由作者绘制)

新手写法

可以使用多个 OR 分隔条件实现上述逻辑。

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)  

优雅的写法

避免使用多个条件语句的方法是使用关键字 in,代码如下:

a = 1  
if a in (1, 2, 3):  
    a += 1  
elif a in (4, 5, 6):  
    a += 5  
else:  
    a *= 2  
print(a) 

18更改列表中所有元素的数据类型

给定一个表示整数的字符串列表,目标修改数据类型将其转换为整数列表。

新手写法

使用 FOR 循环和类型强制转换对单个元素进行变更。

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)  

优雅的写法

聪明的做法是使用 map() 函数,如下所示:

input_list = ["7", "2", "13", "15", "0"]  

output_list = list(map(int, input_list))  

print(output_list)  

map() 函数接收的第一个参数是 function(int),第二个参数是可迭代对象(input_list)。

19交换变量

给定两个变量,目标是对变量值进行交换。

新手写法

大多数C/C++程序员在这里采取的方法是定义一个新的变量(temp),他们通常也会在Python中扩展这个方法。

a = "123"  
b = "abc"  

temp = a  
a = b  
b = temp  
print(a, b)  

优雅的写法

幸运的是,Python 允许在一个语句中进行多次赋值,从而避免了对临时变量的需求。

a = "123"  

b = "abc"  

a, b = b, a  

print(a, b)  

20 使用嵌套循环生成两个列表的所有组合

给定两个列表(a的长度为nb 的长度为 m),生成 (n*m)个组合。

新手写法

编写两个嵌套的FOR循环,并将所有组合追加到列表中。

list1 = ["A", "B", "C"]  

list2 = [1, 2]  

combinations = []  

for i in list1:  

    for j in list2:  

        combinations.append([i, j])  

print(combinations)

优雅的写法

优雅的写法是使用 itertools 库中的 product()方法,如下所示:

from itertools import product  


list1 = ["A", "B", "C"]  

list2 = [1, 2]  


combinations = list(product(list1, list2))  

print(combinations)  

结论

在这篇文章中,我展示了20种不同场景,我相信大多数Python程序员都经历过这些情况,而且可能也采取了错误的编码解决方案,如果你注意到,在大多数情况下,优雅的写法主要侧重于避免使用 FOR 循环进行编码。

作为这篇文章的重点,你应该永远记住,在大多数情况下,你想出的第一个解决方案并不是最优方案,因此,使用谷歌搜索总是有帮助的:),这也是为什么不完美主义的思维方式,对一名讲究的程序员非常重要的原因(不仅是Python,其它语言也一样)。

备注:我很快就会发布这篇文章的第二部分!感谢你的阅读。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/5052.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

几款很好看的爱心表白代码(动态)

分享几款好看的爱心表白代码❤️爱心代码❤️(C语言)❤️流动爱心❤️(htmlcssjs)❤️线条爱心❤️(htmlcssjs)❤️biu表白爱心❤️(htmlcssjs)❤️matlab爱心函数❤️(需…

Java类和对象(一)

🎀作者:爱塔居的博客_CSDN博客-领域博主 🌭专栏:JavaSE 🍧作者简介:大三学生,想要努力地变得更好! 附上一张可可爱爱的猫猫图~ 🍓🍓🍓&#x1f35…

论文学习——多度量水文时间序列相似性分析

文章目录摘要1 研究背景1.1 主要研究内容1.2 研究背景1.3 启发2 基于改进BORDA投票法的多度量水文时间序列相似性分析2.1 研究方法2.2 BORDA投票法的改进2.2.1 BORDA 的缺点2.2.2 改进的BORDA投票法3 实验验证与分析3.1 实验数据3.2 实验结果分析4 结语多度量组合可以提高相似性…

关于使用GB28181协议实现与大华摄像机的语音对讲功能小记

目前只测试了与大华摄像机的语音对讲功能,在此记录下对接工程中遇到的问题和收获。 首先我们需要理清下思路: 第一步要熟悉语音对讲的协议流程,下图为国标28181中的参考图: 这里我们可以简化下流程,只参与与摄像机的…

计算机网络第二章知识点回顾(自顶向下)

第二章知识点回顾1.应用层1.1网络应用架构1.1.1客户-服务器架构1.1.2P2P架构1.1.3两种架构的对比1.2不同终端上的进程通信1.3进程与网络的接口:套接字1.4进程如何标识自己:进程编址1.5因特网提供的传输服务小结1.6Web应用画像1.7 HTTP协议1.7.1HTTP使用T…

大数据技术基础实验十三:Kafka实验——订阅推送示例

大数据技术基础实验十三:Kafka实验——订阅推送示例 文章目录大数据技术基础实验十三:Kafka实验——订阅推送示例一、前言二、实验目的三、实验要求四、实验原理1、Kafka简介2、Kafka使用场景五、实验步骤1、配置各服务器之间的免密登录2、安装ZooKeeper…

【C++】优先级队列 priority_queue的使用模拟实现 | 仿函数

🌈欢迎来到C专栏~~优先级队列的使用 & 模拟实现 (꒪ꇴ꒪(꒪ꇴ꒪ )🐣,我是Scort目前状态:大三非科班啃C中🌍博客主页:张小姐的猫~江湖背景快上车🚘,握好方向盘跟我有一起打天下嘞&#xff01…

聚乙二醇衍生物MAL-PEG-NH2,Maleimide-PEG-amine,CAS:1207751-12-9​

英文:MAL-PEG-NH2,Maleimide-PEG-amine 中文:马来酰亚胺-聚乙二醇-氨基 2、CAS编号:1207751-12-9 3、所属分类:Amine PEG Maleimide PEG 4、分子量:可定制,5000、2000、3400、20000、10000、…

【附源码】Python计算机毕业设计汽车租赁网站

项目运行 环境配置: Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术: django python Vue 等等组成,B/S模式 pychram管理等等。 环境需要 1.运行环境:最好是python3.7.7,…

eBPF学习笔记(一)—— eBPF介绍内核编译

eBPF学习笔记(一)—— eBPF介绍&内核编译eBPF介绍eBPF基础代码验证即时编译eBPF开发工具BCCbpftracelibbpf C/C库eBPF Go库内核编译查看内核版本下载内核源码安装依赖项安装最新版llvm和clang配置内核编译内核BPF示例程序常见问题问题一:…

C++ 堆、大顶堆、小顶堆、堆排序

目录一、什么是堆?1.1 大顶堆1.2 小顶堆1.3 自定义greater1.4 堆索引的特点1.5 堆操作添加元素删除最大元素检查序列是否是堆检查部分序列为堆对堆进行排序升序降序问题:sort()和sort_heap()有什么区别二、排序算法:堆排序2.1 堆排序原理创建…

Bootstrap框架(全)

Bootstrap中文网:点我直达 Bootstrap菜鸟教程:点我直达 目录:(一)Bootstrap标准模板:(二)CSS样式区:一、布局容器:二、栅格系统:1.列组合&#x…

<Linux> 软件包管理器yum及编辑器vim的使用

文章目录一、yum的背景知识1. 商业生态2. 开源生态3. 软件生态本土化二、yum 的基本使用1. 查看软件包2. 安装、卸载、搜索软件实现Windows下和Linux下文件互传三、vim的基本使用1. vim 的基本概念2. vim 的基本操作2.1.模式间切换2.2.插入模式2.3.命令模式2.4.底行模式四、vim…

nginx(四十二)access阶段的模块学习

一 ngx_http_access ① 基本描述 场景: 限制某些ip来源的访问;基于ip进行限制细节点: 基于$remote_addr进行判断的 ② allow deny ③ 官方案例 说明: 按照配置文件中allow|deny的先后顺序,只要匹配上则停止继续匹配 ④ 经典应用场…

Rust机器学习之ndarray

Rust机器学习之ndarray 众所周知,Python之所以能成为机器学习的首选语言,与其丰富易用的库有很大关系。某种程度上可以说是诸如numpy、pandas、scikit-learn、matplotlib、pytorch、networks…等一系列科学计算和机器学习库成就了Python今天编程语言霸主…

Vue项目实战——【基于 Vue3.x + NodeJS】实现的课程表排课系统二(week-title)

文章目录基于 Vue3.x NodeJS实现的课程表排课系统(二)初始化样式封装axios处理数据表格头部(周几)子组件写入根组件App.vue浅拿一下数据基于 Vue3.x NodeJS实现的课程表排课系统(二) 初始化样式 src/ass…

当 AI 遇上 web3,会碰撞出什么火花?

2020 年之前,Web3 的路是创造者们铺好的。但 Web3 遇上了金融,这出乎了每个创造者的意料之外,稳定币、AMM 和借贷突其来地点燃了2020年的那个夏天。之后 Web3 又遇到了 NFT、游戏和元宇宙。不过因为技术限制,除了金融之外&#xf…

AVL树详解(附带旋转步骤图,手把手带你上分)

文章目录👍 AVL树的概念先了解一下😁AVL树节点的定义😊AVL树插入节点🤞AVL树为什么要旋转😍AVL树的四种旋转左单旋右单旋左右双旋右左双旋❤️结语关于AVL树的讲解 👍 AVL树的概念先了解一下 它的左右子树…

Scala005--Scala中的数据结构【集合】之数组

Scala中的数据结构和Java中一样,都有数组,列表,集合,映射。在Scala中与Java不同的是数组可以有可变数组,而不是一旦定义就不可以进行更改。我们来认识数组,并使用相应的代码去查看具体的实现效果。 目录 …

Linux命令从入门到实战 ----进程管理

文章目录kill终止进程pstree查看进程树netstat网络状态和端口占用信息crontab定时任务进程(process): 是正在执行的一个程序或命令,每一个进程都是一个运行的实体,都有自己的地址空间,并占用一定的系统资源 服务(service):启动之后…