高质量Python代码编写的5个优化技巧


Posted in Python onNovember 16, 2017

如今我使用 Python 已经很长时间了,但当我回顾之前写的一些代码时,有时候会感到很沮丧。例如,最早使用 Python 时,我写了一个名为 Sudoku 的游戏(GitHub地址:https://github.com/MichaelWashburnJr/PythonSudoku)。这个游戏在当时算是我比较拿得出手的项目了。然而现在,我无法直接复制其代码并运行它,具体原因是我当时编码时没有添加一个setup.py 或者 requires.txt 文件,当然,这种错误我肯定不会再犯!

由此,我总结了多年来自己所编写的 Python 代码的质量变化过程。它们变得更加简洁、健壮、易读。但是什么原因使得 Python 代码变得更好呢?

在本文中笔者将与大家共同探讨一些 Python 代码的优化手段,或大或小。希望以此帮助你提高 Python 代码的质量。当然,这些方式也可以适用于其他编程语言和技术。

1. 将代码设置为可通过 PIP 安装的软件包

当你想要使用一个新的 Python 包时,如果可以使用 “pip install”命令跟上包名或者包的位置来安装的话,就会非常方便。

有很多方法可以实现这一点,我的“go to”项目实现方法是创建一个 setup.py 文件。

假设我们在“flask_example.py”中有一个简单的 Flask 程序:

from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello_world():
  return 'Hello, World!'

def main():
  app.run()

if __name__ == ‘__main__':
  main()

我们可以将其设置为一个可安装的 Python 包。方法是:首先把它移动到一个单独的文件夹中(我们称之为“flask_example /”),然后在项目根文件夹中创建一个如下所示的setup.py 文件:

from distutils.core import setup

setup(
  name='flask_example',
  version='1.0',
  description='Hello, World! in flask.',
  packages=['flask_example'],
  install_requires=[
    'Flask==0.12.2'
  ],
  entry_points = {
    'console_scripts': 'runserver=flask_example.flask_example:main'
  }
)

这样做可以带来一系列优点。 首先,你可以使用“pip install -e”在本地安装你的应用程序。这样,开发人员可以轻松克隆和安装项目,因为 setup.py 文件将会处理掉所有繁重的工作。

其次,使用 setup.py 文件来进行依赖关系管理。install_requires 变量能够定义要使用的软件包以及版本。如果你不确定使用的软件包名称和版本,可以运行“pip freeze”来查看它们。

最后,它可以为你的程序包定义入口点,通过简单运行“runserver”即可在命令行中执行代码。

2. 借助 linter 工具捕获代码错误

使用 linter(语法检查)可以自动修复代码的语法问题。PyLint 是一款强大的 Python 版本的 linter 工具,如果你使用类似 Git 这样的版本控制系统,可以在提交代码之前让 Git 通过一个 linter 运行代码来解决语法问题。

首先需要安装 PyLint 软件包:

pip install pylint

然后,将以下代码添加到.git/hooks/pre-commit。如果你已经有一个 pre-commit hook,那么只需将 pylint 命令附加到文件的末尾即可。

#!/bin/sh
pylint <your_package_name>

这样做之后就可以在代码提交到 Git 存储库之前自动捕获各种错误。除了语法错误之外,它还能捕捉一些其他的 linter 工具能够捕捉到的常见错误。

3. 尽量使用绝对路径导入而不是相对路径

在 Python 中,使用相对路径导入模块的情况很少(例如 from . import  <模块名>)。如果你已经为 Python 项目创建一个 setup.py(或者使用其他类似的机制)文件,那么你可以简单地通过模块的完整路径引用其子模块。

PEP-8(Python风格指南) 推崇绝对路径导入。这样的话包名更加直观,根据 Python 软件基金会的说法就是“更规范”。

使用相对路径的做法很快就会变成一场噩梦。早期的时候可能没有问题,但是一旦你改名了模块路径或者进行重大的重构之后,它真的会让你很头痛。

4. 上下文管理(with 关键字)

无论何时打开文件、流或者连接,你通常都会使用上下文管理器。上下文管理器很有用,它能够处理文件的关闭并抛出异常。Python 中使用 with 关键字可以很好的实现该功能。

大多数 Python 初学者可能会使用如下方式写入文件:

f = open(‘newfile.txt', ‘w')
f.write(‘Hello, World!')
f.close()

这样做很简单,但是想象一下这种情况:假设你在文件中写入了数千行,不幸的是突然抛出异常,你的文件并未正确关闭,此时你已经写入文件的所有数据都会损坏或者丢失。

不用担心,通过一些简单的重构,即使遇到异常我们也可以确保文件正常关闭。我们可以这样做:

with open(‘file', ‘w') as file:
  file.write(‘Hello, World!')

非常简单!并且代码变得更加简洁。你还可以使用单个“with”语句打开多个上下文管理器,而无需嵌套多个“with”语句。

with open(‘file1', ‘w') as f1, open(‘file2', ‘w') as f2:
  f1.write(‘Hello')
  f2.write(‘World')

5. 使用直观、贴切的函数和变量名

在 Python 中,很容易对函数和返回值产生疑惑。特别是当你调用某些库里的函数时。如果你能够避免开发者通过查询文档才能得知函数功能,这样的时间节省将是一个非常有价值的改进。如何做到呢?如何改变一些简单的变量名称来节省开发时间呢?

在命名函数或变量名时,我会着重考虑3点:

  • 函数或变量的功能
  • 与函数或变量相关联的单位
  • 函数或变量计算的数据类型

例如,如果我想创建一个函数来计算一个矩形的面积,我将函数命名为“calc_rect_area”。但这并没有给用户提供足够的信息。函数会返回值吗?还是将值存储在其他某个地方?返回值的单位是英尺还是米呢?

为了使函数名提供更多信息,我将其修改为“get_rect_area_sq_ft”。这使得用户清楚地知道该函数获取并返回面积,并且单位是英尺。

如果你使用一些更加友好的函数和变量名为开发人员节省5分钟,这些时间累积起来将大大提升开发者的效率。

总结

这些方法是我多年使用 Python 编程所积累的经验。有些是我自己的总结,有些来自他人的指点。我希望上述建议能够助你写出更好的 Python 代码。

作者丨Michael Washburn Jr.
译者丨安翔

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python单链表的简单实现方法
Sep 23 Python
Python操作MySQL简单实现方法
Jan 26 Python
使用IPython来操作Docker容器的入门指引
Apr 08 Python
Windows上配置Emacs来开发Python及用Python扩展Emacs
Nov 20 Python
Python中常用信号signal类型实例
Jan 25 Python
Python二叉树的遍历操作示例【前序遍历,中序遍历,后序遍历,层序遍历】
Dec 24 Python
利用python求积分的实例
Jul 03 Python
python 实现turtle画图并导出图片格式的文件
Dec 07 Python
django框架中ajax的使用及避开CSRF 验证的方式详解
Dec 11 Python
Python统计时间内的并发数代码实例
Dec 28 Python
Python如何将字符串转换为日期
Jul 31 Python
Python面向对象多态实现原理及代码实例
Sep 16 Python
python使用fork实现守护进程的方法
Nov 16 #Python
详解Python map函数及Python map()函数的用法
Nov 16 #Python
python中lambda()的用法
Nov 16 #Python
Python reduce()函数的用法小结
Nov 15 #Python
python简单实例训练(21~30)
Nov 15 #Python
python下10个简单实例代码
Nov 15 #Python
python获取多线程及子线程的返回值
Nov 15 #Python
You might like
在php和MySql中计算时间差的方法
2011/04/22 PHP
php通过ksort()函数给关联数组按照键排序的方法
2015/03/18 PHP
Linux服务器下PHPMailer发送邮件失败的问题解决
2017/03/04 PHP
defer属性导致引用JQuery的页面报“浏览器无法打开网站xxx,操作被中止”错误的解决方法
2010/04/27 Javascript
Jquery+CSS3实现一款简洁大气带滑动效果的弹出层
2013/05/15 Javascript
JavaScript事件处理器中的event参数使用介绍
2013/05/24 Javascript
2014最热门的JavaScript代码高亮插件推荐
2014/11/25 Javascript
js与css实现弹出层覆盖整个页面的方法
2014/12/13 Javascript
深入探寻javascript定时器
2015/01/02 Javascript
详谈javascript中DOM的基本属性
2015/02/26 Javascript
快速获取/设置iframe内对象元素的几种js实现方法
2016/05/20 Javascript
AngularJS ng-app 指令实例详解
2016/07/30 Javascript
JS图片等比例缩放方法完整示例
2016/08/03 Javascript
js+css3制作时钟特效
2016/10/16 Javascript
jquery-mobile基础属性与用法详解
2016/11/23 Javascript
Bootstrap输入框组件使用详解
2017/06/09 Javascript
AngularJS基于provider实现全局变量的读取和赋值方法
2017/06/28 Javascript
js实现音乐播放控制条
2017/09/09 Javascript
对angularJs中$sce服务安全显示html文本的实例
2018/09/30 Javascript
写gulp遇到的ES6问题详解
2018/12/03 Javascript
详解Vue依赖收集引发的问题
2019/04/22 Javascript
小程序自定义导航栏兼容适配所有机型(附完整案例)
2020/04/26 Javascript
vue使用echarts实现水平柱形图实例
2020/09/09 Javascript
[06:11]2014DOTA2国际邀请赛 专访团结一心的VG战队
2014/07/21 DOTA
用python实现对比两张图片的不同
2018/02/05 Python
使用Python制作表情包实现换脸功能
2019/07/19 Python
Python使用__new__()方法为对象分配内存及返回对象的引用示例
2019/09/20 Python
python单向链表的基本实现与使用方法【定义、遍历、添加、删除、查找等】
2019/10/24 Python
django-利用session机制实现唯一登录的例子
2020/03/16 Python
Python ckeditor富文本编辑器代码实例解析
2020/06/22 Python
Rentalcars.com中国:世界上最大的在线汽车租赁服务
2019/08/22 全球购物
美国购买体育、音乐会和剧院门票网站:SelectATicket
2019/09/08 全球购物
Ajax请求总共有多少种Callback
2016/07/17 面试题
中学优秀班主任事迹材料
2014/05/01 职场文书
在校实习生求职信
2014/06/18 职场文书
四风问题对照检查材料思想汇报
2014/10/07 职场文书