成为Python高手,我能给出的最好建议

news2024/11/17 9:37:40

今天笔者将向大家分享5个良好的Python编程习惯,大牛认证,通过不断实践,助你写出更Pythonic的代码,让你向Python大师之路更进一步。

今天笔者将向大家分享5个良好的Python编程习惯,大牛认证,通过不断实践,助你写出更Pythonic的代码,让你向Python大师之路更进一步。

1. 常用if __name__ == '__main__'

假设我们在 module.py 中写了一个模拟连接到数据库的函数,并调用它:

复制

输出:

复制

Connecting to database...
Connected to database successfully!

现在,假设我们保持 module.py 的代码不变,然后在 main.py 中调用 sim_conn_to_db() 方法:

复制

from module import sim_conn_to_db

sim_conn_to_db()
输出:

复制

Connecting to database...
Connected to database successfully!
Connecting to database...
Connected to database successfully!

wow,你发现了么?sim_conn_to_db() 方法执行了两遍。这是为什么呢?原因在于我们通过 from module import sim_conn_to_db 语句引入 sim_conn_to_db() 方法时,Python解释器会加载整个 module.py 脚本,逐行加载代码。因此,在加载的时候已经执行了一次 sim_conn_to_db() 方法;然后,在 main.py 脚本中我们又再一次调用了 sim_conn_to_db() 方法,所以,该方法被执行了2次。

那么改如何避免这种情况呢?这就是今天我向大家分享的第1个好习惯,总是使用 if __name__ == '__main__' 语句执行检查。比如,在 module.py 文件中加入改语句:

复制

import time

def sim_conn_to_db() -> None:
    print('Connecting to database...')
    time.sleep(3)
    print('Connected to database successfully!')

if __name__ == '__main__':
    sim_conn_to_db()

然后,我们再次执行 main.py 文件,sim_conn_to_db() 方法就不会被执行2次。因为 if __name__ == '__main__' 语句确保了只有直接执行 module.py 文件的时候,sim_conn_to_db() 方法才会被调用,在别的 .py 文件中调用该方法时只会执行一次。

如果你使用的Pycharm IDE的话,if __name__ == '__main__' 的另一个好处就是,在行号处会出现一个绿色的运行按钮,单击该按钮你可以直接执行当前脚本文件或其他操作.

2.main函数让代码更有组织性

假设我们有以下代码片段:

复制

def greeting(name: str) -> None:
    print(f"Hello {name}!")

def bye() -> None:
    print("Bye! See you soon!")

if __name__ == '__main__':
    greeting(name='Jack')
    bye()

这里,我们定义了两个简单的问候和告别方法,并且调用它们。完全没有问题,正确实现了预期功能。但是,如果有很多个函数呢?也在 if __name__ == '__main__': 语句中调用的话就显得臃肿且复杂,毫无组织性。因为 if __name__ == '__main__': 语句是函数的执行入口,我们应该尽量保证简洁。

这个时候就用到了今天我给大家分享的第2个好习惯,定义一个 main 函数,将所有函数调用和其他逻辑都放到该函数中,然后在入口处只需要调用 main 函数即可。

复制

def greeting(name: str) -> None:
    print(f"Hello {name}!")

def bye() -> None:
    print("Bye! See you soon!")

def main() -> None:
    greeting(name='Jack')
    bye()

if __name__ == '__main__':
    main()

这样,即使后续有新增的方法调用,只需要在main函数中添加即可,不仅确保了脚本运行入口处语句的简洁,同时让整个代码结构更具组织性。另一方面,也让你的代码更具可读性。

Tips:你可以将 main 函数当做是你的管家,无论多复杂、数量众多的事务都交给管家一个人去统筹安排,而你只需要掌控管家一个人即可。

3. 保持函数的单一性和简洁性

假设我们有一个根据姓名、年龄和身份证来判断某人是否能够加入俱乐部的方法,如下:

复制

def enter_club(name: str, age: int, has_id: bool) -> None:
    if name.lower() == 'stefan':
        print('Get out of here Stefan, we don\'t want to trouble.')

    if age >= 18 and has_id:
        print('You may enter the job.')
    else:
        print('Sorry, you may not enter the club.')

def main() -> None:
    enter_club(name='Stefan', age=18, has_id=True)
    enter_club(name='Bob', age=29, has_id=True)
    enter_club(name='Ellena', age=20, has_id=False)
    enter_club(name='Bony', age=21, has_id=True)

if __name__ == '__main__':
    main()

很明显,上面的代码正确实现了我们想要的功能。但我并不推荐这种做法,因为 enter_club 方法中涉及了很复杂的逻辑,并不符合Python函数编程的单一职责原则。

因此,这里就会用到今天我给大家分享的第3个好习惯——尽可能保持函数的单一性和简洁性。enter_club 方法中同时涉及到姓名、年龄和身份的判断,实际上我们可以将其拆分成多个具有单一职责的函数。

复制

def is_black_list(name: str) -> bool:
    return name.lower() == 'stefan'

def is_adult(age: int, has_id: bool) -> bool:
    return age >= 18 and has_id

def enter_club(name: str, age: int, has_id: bool) -> None:
    if is_black_list(name):
        print('Get out of here Stefan, we don\'t want to trouble.')

    if is_adult(age, has_id):
        print('You may enter the job.')
    else:
        print('Sorry, you may not enter the club.')

def main() -> None:
    enter_club(name='Stefan', age=18, has_id=True)
    enter_club(name='Bob', age=29, has_id=True)
    enter_club(name='Ellena', age=20, has_id=False)
    enter_club(name='Bony', age=21, has_id=True)

if __name__ == '__main__':
    main()

这里,我们将对姓名和年龄、身份的判断拆分为两个独立的方法 is_black_list 和 is_adult。拆分后的函数职责单一,逻辑简单清晰。确保实现相同功能的同时,增强了代码的可读性、可维护性以及可扩展性。

4. 尽可能多用类型提示

第4个好习惯就是类型注释(type hints),如果你还不知道什么是类型注释,以及它的诸多好处,你可以阅读我的上一篇文章“Python类型提示(type hints):提升代码质量与可读性的利器!”。

这里,我们只是举几个简单的例子来说明类型注释的实用之处。

4.1 降低代码潜在bug或错误的风险

比如,以下代码段:

复制

def add(a, b):
    return a + b

if __name__ == '__main__':
    result = add(a=1, b=2)
    print(result)  # 3

正确实现了整数的加法功能。但是,由于参数 a 和 b 并没有任何类型说明,如果你的用户或同事在调用 add 方法时,给了错误的参数类型,很可能造成意料之外的结果甚至程序错误,比如,

复制

def add(a, b):
    return a + b

if __name__ == '__main__':
    result = add(a='1', b=2)
    print(result)

只要给参数 a传递字符串值,都会导致 TypeError,因为字符串和整数不支持连接操作。类似地,如果给参数 b 传递字符串值,同样会得到 TypeError,因为整数和字符串不支持加法操作。

然而,如果给参数 a 和 b 都传递字符串值,会发生什么呢:

复制

虽然程序可以正常执行,但是得到的结果是12,这是字符串连接结果,而不是我们想要的整数相加结果。

解决这种潜在错误或不期望结果的方法就是在方法定义中使用类型注释:

复制

def add(a: int, b: int) -> int:
    return a + b

这样,在方法调用时,如果给参数传递了不符合定义时所给的参数类型,编译器会提示

有了这个提示,我们就知道应该给参数传递的是整数类型,而不是字符串。有效降低了潜在bug或错误发生的几率,特别是在大型项目中。因为解决bug永远都是一件令人十分恼火的事😫😫😫。

4.2 提高编码效率

在很多IDE中,都提供了根据上下文进行代码补齐的功能,比如Pycharm。但是,如果不知道变量类型的前提下,编译器是没办法给你任何推荐的。比如:

这里,我想对一个DataFrame进行一系列的处理,由于不知道变量的数据类型,在输入 . 之后,编译器无法给出有效的推荐。

当我们增加类型注释后:

这时,编译器就会将DataFrame具有的所有方法和属性全都列出来供我们选择,可以快速找到我们想要的方法或属性,从而提高编码效率。

关于类型注释的更多用法,你可以阅读我的上一篇文章“Python类型提示(type hints):提升代码质量与可读性的利器!”。

5. 善用列表推导式

假设有一个不同年龄构成的列表,我们想要筛选出所有大岁数(年龄≥30)的人并存储在新的列表中:

复制

ages: list[int] = [18, 16, 20, 35, 40, 53, 65, 32, 80, 96]

olders: list[int] = list()
for age in ages:
    if age >= 30:
        olders.append(age)
print(f'People with older age: {olders}')
# Output: People with older age: [35, 40, 53, 65, 32, 80, 96]

这里我们通过循环实现了想要的功能。但其实,还有另一种更简洁的方法,就是今天我给大家分享的最后一个好习惯——善用列表推导式:

复制

ages: list[int] = [18, 16, 20, 35, 40, 53, 65, 32, 80, 96]

olders: list[int] = [age for age in ages if age >= 30]
print(f'People with older age: {olders}')

完整实现相同功能的同时,一下子将4行的核心代码编程1行,是不是既简洁又高效呢?

结语

作为开发者,我们需要保持好奇心和学习热情,不断探索新的技术,只有这样,我们才能在这个快速发展的时代中立于不败之地。介绍一款程序员都应该知道的软件JNPF快速开发平台,很多人都尝试用过它,它是功能的集大成者,任何信息化系统都可以基于它开发出来。

JNPF可以实现应用从创建、配置、开发、测试到发布、运维、升级等完整生命周期的管理。减少了传统应用程序的代码编写量,通过图形化、可视化的界面,以拖放组件的方式,即可快速生成应用程序的产品,大幅降低了开发企业管理类软件的难度。

当然,我更建议大家成为一个全栈,不要把自己的定位局限于前端。

感谢阅读本文

如果有什么建议,请在评论中让我知道。我很乐意改

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

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

相关文章

Java面试题精选:消息队列(二)

一、Kafka的特性 1.消息持久化:消息存储在磁盘,所以消息不会丢失 2.高吞吐量:可以轻松实现单机百万级别的并发 3.扩展性:扩展性强,还是动态扩展 4.多客户端支持:支持多种语言(Java、C、C、GO、…

WPF中如何根据数据类型使用不同的数据模板

我们在将一个数据集合绑定到列表控件时,有时候想根据不同的数据类型,显示为不同的效果。 例如将一个文件夹集合绑定到ListBox时,系统文件夹和普通文件夹分别显示为不同的效果,就可以使用模板选择器功能。 WPF提供了一个模板选择…

查找4(散列表)

1)基本概念 、 2)散列函数的构造 3)解决冲突 I)开放地址发 II)链地址法 4)散列表的查找

vs2022 C++ 使用MySQL Connector/C++访问mysql数据库

1、下载MySQL Connector/C,我这里下载的是debug版本,下载链接MySQL :: Download MySQL Connector/C (Archived Versions) 2、解压并且放到MySQL文件夹中,便于使用 3、打开vs2022,右键项目,点击属性 4、在 “C/C” ->…

el-input中show-password密码提示功能去掉

el-input中show-password密码提示功能去掉 一、效果图二、封装个组件三、如何使用 一、效果图 二、封装个组件 <template><divclass"el-password el-input":class"[size ? el-input-- size : , { is-disabled: disabled }]"><inputclass…

Java线上监控诊断产品Arthas(续集)

Java线上监控诊断产品Arthas&#xff08;续集&#xff09; 前言1.auth指令2.monitor指令解读 3.classloader指令场景 4.dump指令场景 5.getstatic指令场景 6.heapdump指令场景 7.profiler指令场景 8.sc指令场景 9.trace指令场景 前言 在去年&#xff0c;我发表了一片文章&…

心血管内科常用评估量表汇总,附操作步骤与评定标准

心血管内科常用量表来评估患者病情、预测风险&#xff0c;量表在制定治疗方案和预测疾病进展等方面发挥着重要作用。常笑医学整理了6个心血管内科常用的评估量表&#xff0c;支持下载和在线使用&#xff0c;供临床医护人员参考。 01 GRACE缺血风险评估 &#xff08;完整量表请点…

Qt 学习第7天:Qt核心特性

元对象系统Meta-object system 来自AI生成&#xff1a; Qt中的元对象系统&#xff08;Meta-Object System&#xff09;是Qt框架的一个核心特性&#xff0c;它为Qt提供了一种在运行时处理对象和类型信息的能力。元对象系统主要基于以下几个关键概念&#xff1a; 1. QObject&a…

【91-136】行为型模式

目录 一.模板方法模式 1.1 概述 1.2 结构 1.3 案例 1.4 优缺点 1.5 使用场景 二.策略模式 2.1 概述 2.2 结构 2.3 案例 2.4 优缺点 2.5 使用场景 2.6 JDK 源码解析 三.命令模式 3.1 概述 3.2 结构 3.3 案例 3.4 优缺点 3.5 使用场景 四.责任链模式 4.1 概…

NeRF: Representing Scenes as Neural Radiance Fields for View Synthesis 翻译

NeRF&#xff1a;将场景表示为用于视图合成的神经辐射场 引言。我们提出了一种方法&#xff0c;该方法通过使用稀疏的输入视图集优化底层连续体场景函数来实现用于合成复杂场景的新视图的最新结果。我们的算法使用全连通&#xff08;非卷积&#xff09;深度网络来表示场景&…

设计模式(一):七大原则

*设计模式的目的* 编写软件过程中,程序员面临着来自耦合性,内聚性以及可维护性,可扩展性,重用性,灵活性等多方面的挑战,设计模式是为了让程序(软件),具有更好 1) 代码重用性 (即:相同功能的代码,不用多次编写) 2) 可读性 (即:编程规范性, 便于其他程序员的阅读和理…

【C++ 第十七章】封装 unordered_map / unordered_set

声明&#xff1a;上一章讲解了 哈希结构的原理与实现&#xff0c;本章主要将上一章学过的拉链法的哈希结构封装进 unordered_map / unordered_set&#xff0c;所以需要先学过相关知识&#xff0c;才能更好吸收本章知识 上一章的链接&#xff1a;【C 第十六章】哈希 1. unorder…

Ubuntu24.04 安装向日葵远程访问工具

目录 安装向日葵远程访问工具 解决方案&#xff1a; 1.下载软件包 2.远程Ubuntu桌面控制卡住 卸载向日葵远程访问工具 安装向日葵远程访问工具 安装命令&#xff1a;sudo dpkg -i 文件名.deb sudo dpkg -i SunloginClient_15.2.0.63064_amd64.deb 提示错误如下&#xf…

后端修改资源后重新运行项目了,浏览器刷新资源没更新问题

修改后重启项目&#xff0c;去浏览器刷新&#xff1a; 没有改变&#xff1f; 解决办法&#xff1a; F12去调试器里“网络”工具栏下找到“禁用缓存”按钮即可解决

视频转换成文字的5种方法,看一遍就能学会

视频已成为我们获取信息的重要渠道之一。然而&#xff0c;有时我们更需要将视频中的精华内容以文字形式提取出来&#xff0c;以便进行编辑、整理或分享。今天&#xff0c;就为大家介绍五种视频转换成文字的高效方法&#xff0c;一起来了解下吧。 方法一&#xff1a;口袋视频转换…

如何抠图把背景换成透明怎么做?

要抠图并将背景变为透明&#xff0c;这样做的好处是可以方便地将所选物体从原始图像中分离出来&#xff0c;并在其他背景上自由组合。怎么把图片变成透明底&#xff0c;抠图攻略分享&#xff1a;让你轻松上手抠图&#xff01; 通过抠图和背景透明化&#xff0c;您可以创建更多种…

深入理解微服务中的负载均衡算法与配置策略

负载均衡算法 我们首先来探讨一下默认情况下Ribbon使用的负载均衡算法。有些人可能会说它使用轮询算法&#xff0c;因为在本地测试时&#xff0c;我们经常会看到轮询的效果。然而&#xff0c;简单地依赖这种表面的观察来回答面试题是有风险的。实际上&#xff0c;忽略了深入理解…

Superset 无需登录访问分享的图表

1&#xff0c;进入Superset安装目录找到config.py文件 2&#xff0c;修改config.py中的配置项 添加 PUBLIC_ROLE_LIKE: Optional[str] "Gamma" # Grant public role the same set of permissions as for a selected builtin role. # This is useful if one wants to…

Large Bin Attack 源码调试

Large Bin Attack 分配跟 large bin 有关的 chunk&#xff0c;要经过 fastbin&#xff0c;unsorted bin&#xff0c;small bin 的分配&#xff0c;建议在学习 large bin attack 之前搞清楚 fastbin&#xff0c;unsorted bin 分配的流程。 large bin中双向链表的连接方法&…

五款伪原创文章生成器软件,为创作者快速生成高质量内容

在内容为王的时代&#xff0c;创作者们面临着巨大的压力&#xff0c;需要不断地产出高质量、有深度的文章。在这个过程中&#xff0c;伪原创文章生成器软件成为了许多创作者的得力助手。本文将为你详细介绍5款伪原创文章生成器软件&#xff0c;帮助你快速生成高质量内容。 一、…