Python开发者用Pythonic这个形容词来描述具有特定风格的代码。这种风格是大家在使用Python语言进行编程并相互协作的过程中逐渐形成的习惯。那么,如何以改风格完成常见的Python编程工作呢?本节将会回答这个问题。

  • 第一条:确认自己所用的Python版本

  • 第二条:遵循PEP8风格指南

  • 第三条:了解bytes、str与unicode的区别

  • 第四条:用辅助函数来取代复杂的表达式

  • 第五条:了解切割序列的方法

  • 第六条:在单次切片操作内,不要同时指定start、end和stride

  • 第七条:用列表推导来取代map和filter

  • 第八条:不要使用含有两个以上表达式的列表推导

  • 第九条:用生成器表达式来改写数据量较大的列表推导

  • 第十条:尽量用enumerate取代range

  • 第十一条:用zip函数同时遍历两个迭代器

  • 第十二条:不要在for和while循环后面写else块

  • 第十三条:合理利用try/exceot/else/finally结构中的每个代码块

第一条:确认自己所用的Python版本

C:\Users\fei\Desktop>python --version
Python 3.6.5 import sys
sys.version
Out[14]: '3.6.5 (v3.6.5:f59c0932b4, Mar 28 2018, 17:00:18) [MSC v.1900 64 bit (AMD64)]'

要点

  • 要点1:有两个版本的Python处于活跃状态,它们是:Python2和Python3

  • 要点2:有很多中流行的Python运行时环境,例如: Cpython, Jython,IronPython以及PyPy等

  • 要点3:在操作系统的命令行中运行Python时,请确保该Python的版本与你想使用的Python版本相符。

  • 要点4:由于Python社区把开发重点放在Python3上,所以在开发后序项目时,应该优先考虑采用Python3

第二条:遵循PEP8风格指南

《Python Enhancement Proposal #8》(8号Python增强提案)又叫PEP8,它是针对Python代码格式而编订的风格指南。尽管可以在保证语法正确的前提下随意编写Python代码,但是采用一致的风格书写代码可以令代码更加易懂、更加易读。

完整版PEP8指南

  1. PEP 8 -- Style Guide for Python Code

  2. PEP8中文翻译

下面列出几条绝对应该遵守的规则

空白: Python中的空白( whitespace)会影响代码的含义。 Python程序员使用空白 的时候尤其在意,因为它们还会影响代码的清晰程度。

  • 使用 space(空格)来表示缩进,而不要用tab(制表符)。

  • 和语法相关的每一层缩进都用4个空格来表示。

  • 每行的字符数不应超过79。

  • 对于占据多行的长表达式来说,除了首行之外的其余各行都应该在通常的缩进 级别之上再加4个空格。

  • 文件中的函数与类之间应该用两个空行隔开。

  • 在同一个类中,各方法之间应该用一个空行隔开。

  • 在使用下标来获取列表元素、调用函数或给关键字参数赋值的时候,不要在两 旁添加空格。

  • 为变量赋值的时候,赋值符号的左侧和右侧应该各自写上一个空格,而且只写 个就好。

命名:PEP8提倡采用不同的命名风格来编写 Python代码中的各个部分,以便在阅 读代码时可以根据这些名称看出它们在 Python语言中的角色。

  • 函数、变量及属性应该用小写字母来拼写,各单词之间以下划线相连,例如lowercase_underscore。

  • 受保护的实例属性,应该以单个下划线开头,例如, leading underscore

  • 私有的实例属性,应该以两个下划线开头,例如, double leading underscore

  • 类与异常,应该以每个单词首字母均大写的形式来命名,例如, Capitalized Word 口模块级别的常量,应该全部采用大写字母来拼写,各单词之间以下划线相连, 例如, ALL CAPS。

  • 类中的实例方法( instance method)。应该把首个参数命名为sef,以表示该对象自身

  • 类方法( lass method)的首个参数,应该命名为cbs,以表示该类自身。

表达式和语句:( The Zen of Python)( Python之禅)中说:“每件事都应该有直白的做 法,而且最好只有一种。”PEP8在制定表达式和语句的风格时,就试着体现了这种思想。

  • 采用内联形式的否定词,而不要把否定词放在整个表达式的前面,例如,应该 写 if a is not b而不是 if not a is b。

  • 不要通过检测长度的办法(如 if len(somelist)=0)来判断 somalis是否为目 或”等空值,而是应该采用 if not somelist这种写法来判断,它会假定:空值将 自动评估为 False

  • 检测 somalis是否为]或hi等非空值时,也应如此, if somelist语句默认会把 非空的值判断为Tme。

  • 不要编写单行的i语句、for循环、 while循环及cxp复合语句,面是应该把 这些语句分成多行来书写,以示清晰。

  • import语句应该总是放在文件开头。

  • 引入模块的时候,总是应该使用绝对名称,而不应该根据当前模块的路径来 使用相对名称。例如,引入bar包中的foo模块时,应该完整地写出 from bar import foo,面不应该简写为 import foo。

  • 如果一定要以相对名称来编写ipon语句,那就采用明确的写法: from import food 口文件中的那些mpon语句应该按顺序划分成三个部分,分别表示标准库模块 第三方模块以及自用模块:在每一部分之中,各如m语句应该按模块的字母 顺序来排列。

要点

  • 要点1:当编写Python代码时,总是应该遵循PEP8风格指南。

  • 要点2:与广大Python开发者采用同一套代码风格,可以使项目更利于多人协作。

  • 要点3: 采用一致的风格来编写代码,可以令后续的修改工作变得更为容易。

第三条:了解bytes、str与unicode的区别

Python3有两种表示字符序列的类型:bytes和str。前者的实例包含原始的8位值;后者的实例包含Unicide字符。

Python2也有两种表示字符序列的类型,分别叫做str和unicode。与Python3不同的是,str的实例包含原始的8位值;而unicode的实例,则包含Unicode字符。

注:unicode --> 二进制     encode方法

  二进制  --> unicode    decode方法

要点:

  • 要点1:在Python3中,bytes是一种包含8位值的序列,str是一种包含unicoe字符的序列。开发者不能以>或+等操作符来混同操作bytes和str实例

  • 要点2:在Python2中,str是一种包含8位值的序列,unicode是一种包含Unicode字符的序列。如果str只包含有7位ASCII字符,那么可以通过相关额操作符同时使用str与unicode。

  • 要点3:在对输入的数据进行操作之前,使用辅助函数来保证字符序列的类型与开发者的期望相符(有的时候,开发者想操作以UTF-8格式来编码的8位值,有的时候,则想操作Unicode字符)。

  • 要点4:从文件中读取二进制数据,或向其中写入二进制数据时,总应该以‘rb'或‘wb’等二进制模式来开启文件。

第四条:用辅助函数来取代复杂的表达式

要点:

  • 要点1:开发者很容易过度运用Python的语法特性,从而写出那种特别复杂并且难以理解的单行表达式

  • 要点2:请把复杂的表达式移入辅助函数之中,如果要反复使用相同的逻辑,那就更应该这样做

  • 要点3:使用if/else表达式,要比用or或and这样的Boolean操作符写成的表达式更加清晰。

第五条:了解切割序列的方法

要点:

  • 要点1:不要写多余的代码:当start索引为0,或end索引为序列长度时,应该将其省略。

  • 要点2:切片操作不会计较start与end索引是否越界,这使得我们很容易就能从序列的前端或后端开始,对其进行范围固定的切片操作(如a[:20]或a[-20:])。

  • 要点3:对list赋值的时候,如果使用切片操作,就会把原列表处在相关范围内的值替换成新值,即使他们的长度不同也依然可以替换。

  • 要点4:如果对赋值操作右侧的列表使用切片,而把切片的起止索引都留空,那就会产生一份原列表的拷贝。
  • 要点5:如果对赋值左侧的列表使用切片,而又没有指定起止索引,那么系统会把右侧的新值复制一份,并好用这份拷贝替换左侧列表的全部内容,而不会重新分配新的列表。

示例代码

a = [1,2,3,4,5]
b = a
id(a)
Out[4]: 588602575880
id(b)
Out[5]: 588602575880
c = a[:]
id(c)
Out[7]: 588602487112
a
Out[8]: [1, 2, 3, 4, 5]
id(a)
Out[9]: 588602575880
a[2:4] = [10,11]
id(a)
Out[11]: 588602575880
a
Out[12]: [1, 2, 10, 11, 5]
a[2:4] = [2,2,2,2,2]
a
Out[14]: [1, 2, 2, 2, 2, 2, 2, 5]
id(a)
Out[15]: 588602575880

第六条:在单次切片操作内,不要同时指定start、end和stride

要点

  • 要点1:既有start和end,又有stride的切割操作,可能会令人费解。

  • 要点2:尽量使用stride为整数,切不带start或end索引的切割操作。尽量避免用负数做sride.

  • 要点3:再同一个切片操作内,不要同时使用start、end和stride。如果确实需要执行这种操作,那就考虑将其拆解为两条赋值语句,其中一角做范围切割,另一条做步进切割,或考虑使用内置函数itertools模块中的islice。

第七条:用列表推导来取代map和filter

  • 要点1: 列表推导比内置的map和filter函数清晰, 因为它无需额外编写lanbda表达式

  • 要点2:  列表推导可以跳过输入列表中的某些元素,如果改用map来做,那就必须辅以filter方能实现

  • 要点3:字典和集合也支持列表推导

第八条:不要使用含有两个以上表达式的列表推导

  • 要点1: 列表推导支持多级循环,每一级循环也支持多项条件

  • 要点2: 超过两个表达式的列表推导式很难理解的,应该尽量避免

第九条:用生成器表达式来改写数据量较大的列表推导

  • 要点1: 当输入数据量较大时,列表推导可能会因为占用太多内存而出问题

  • 要点2: 由生成器表达式所返回的迭代器,可以逐次产生输出值,从而避免了内存用量问题。

  • 要点3: 把某个生成器表达式所返回的迭代器,放在另一个生成器表达式的for子表达式中,即可将二者组合起来

  • 要点4: 串在一起的生成器表达式执行速度很快。

第十条:尽量用enumerate取代range

  • 要点1:enumerate函数提供了一种精简的写法,可以在遍历迭代器时获知每个元素的索引

  • 要点2: 尽量用enumerate来改写那种将range与下标访问相结合的序列遍历代码

  • 要点3: 可以给enumerate提供第二个参数,已制定开始技术是所用的值(默认为0)

第十一条:用zip函数同时遍历两个迭代器

  • 要点1: 内置的zip函数可以平行的遍历多个迭代器

  • 要点2: Python3中的zip相当于生成器,会在遍历过程中逐次产生元组,而Python2中的zip则是直接把元组完全生成好,并一次性返回整份列表。

  • 要点3: 如果提供的迭代器长度不等,那么zip就会自动提前终止

  • 要点4:itertools内置模块中的zip_longest函数可以平行地遍历多个迭代器,而不用在乎它们的长度是否相等

第十二条:不要在for和while循环后面写else块

  • 要点1: Python有种也属于语法,可在for及while循环的内部语句块之后紧跟一个else块

  • 要点2: 只有当整个循环主体都没遇到break语句时,循环后面的else块才会执行

  • 要点3: 不要在循环后面使用else块,因为这种写法既不直观,又容易引起误解

第十三条:合理利用try/exceot/else/finally结构中的每个代码块

  • 要点1: 无论try块是否发生异常,都可利用try/finally复合语句中的finally块来执行清理工作

  • 要点2: else块可以用来缩减try块中的代码量,并把没有发生异常时所要执行的语句与try/except代码块隔开

  • 要点3: 顺利运行try块后,若想使某些操作能在finally块的清理代码之前执行,则可将这些操作写到else块中。

编写高质量的Python代码系列(一)之用Pythonic方式来思考的更多相关文章

  1. 编写高质量的Python代码系列(八)之部署

    Python提供了一些工具,使我们可以把软件部署到不同的环境中.它也提供了一些模块,令开发者可以把程序编写的更加健壮.本章讲解如何使用Python调试.优化并测试程序,以提升其质量与性能. 第五十四条 ...

  2. 编写高质量的Python代码系列(七)之协作开发

    如果多个人要开发同一个Python程序,那就得仔细商量代码的写法了.即使你是一个人开发,也需要理解其他人所写的模块.本节讲解多人协作开发Python程序时所用的标准工具及最佳做法. 第四十九条:为每个 ...

  3. 编写高质量的Python代码系列(六)之内置模块

    Python预装了许多写程序时会用到的重要模块.这些标准软件包与通常意义上的Python语言联系得非常精密,我们可以将其当成语言规范的一部分.本节将会讲解基本的内置模块. 第四十二条:用functoo ...

  4. 编写高质量的Python代码系列(四)之元类及属性

    元类(metaclass)及动态属性(dynamic attribute)都是很强大的Python特性,然后他们也可能导致及其古怪.及其突然的行为.本节讲解这些机制的常见用法,以确保各位程序员写出来的 ...

  5. 编写高质量的Python代码系列(三)之类与继承

    用Python进行编程时,通常需要编写心累,并定义这些类应该如何通过其接口及继承体系与外界交互.本节讲解如何使用类和继承来表达对象所以更具备的行为. 第二十二条:尽量用辅助类来维护程序的状态,而不要用 ...

  6. 编写高质量的Python代码系列(二)之函数

    Python中的函数具备多种特性,这可以简化编程工作.Python函数的某些性质与其他编程语言中的函数相似,但也有性质是Python独有的.本节将介绍如何用函数来表达亿图.提升可复用程度,并减少Bug ...

  7. 编写高质量的Python代码系列(五)之并发与并行

    用Python可以很容易就能写出并发程序,这种程序可以在同一时间做许多间不同的事情.我们也可以通过系统调用.子进程(subprocess)及C语言扩展来实现并行处理. 第三十六条: 用subproce ...

  8. iOS应用开发最佳实践系列一:编写高质量的Objective-C代码

          本文由海水的味道编译整理,转载请注明译者和出处,请勿用于商业用途! 点标记语法 属性和幂等方法(多次调用和一次调用返回的结果相同)使用点标记语法访问,其他的情况使用方括号标记语法. 良好的 ...

  9. HTML Inspector – 帮助你编写高质量的 HTML 代码

    HTML Inspector 是一款代码质量检测工具,帮助你编写更优秀的 HTML 代码.HTML Inspector 使用 JavaScript 编写,运行在浏览器中,是最好的 HTML 代码检测工 ...

随机推荐

  1. Win10 Service'MongoDB Server' failed to start. Verify that you have sufficient privileges to start system services【简记】

    最近工作中有需要用到 MongoDB数据库,以前用的3.*的版本,这次用的是较新4.0.6的版本,然后去官网下载安装. 安装到一半,就弹出如下提示,说是"MongoDB Server&quo ...

  2. Java MultipartFile 使用记录

    private void file(String path,MultipartFile file){ String separator = "/"; String originFi ...

  3. SpringMVC处理请求和返回流程

    流程描述:一个url请求,找打指定的requestMapping再返回指定的jsp界面 通过url拿到指定的java方法 HandlerExecutionChain  mappedHandler = ...

  4. Linux内存管理 (13)回收页面

    专题:Linux内存管理专题 关键词:LRU.活跃/不活跃-文件缓存/匿名页面.Refault Distance. 页面回收.或者回收页面也即page reclaim,依赖于LRU链表对页面进行分类: ...

  5. flask token认证

    在前后端分离的项目中,我们现在多半会使用token认证机制实现登录权限验证. token通常会给一个过期时间,这样即使token泄露了,危害期也只是在有效时间内,超过这个有效时间,token过期了,就 ...

  6. 家庭记账本小程序之增(java web基础版三)

    实现新增消费账单 1.main_left.jsp中该部分,调用add.jsp 2. add.jsp,提交到Servlet的add方法 <%@ page language="java&q ...

  7. web 日历 任务 插件

    [2] 日历任务插件(jquery版)新增日历任务和点击监听 - qq_26462567的博客 - CSDN博客https://blog.csdn.net/qq_26462567/article/de ...

  8. js中“==”与“===”区别

    直接上代码 if(2==='2'){ console.log(true) }else{ console.log(false) } //打印结果 false if(2=='2'){ console.lo ...

  9. SaxReader读取xml

    package com.java1234.action; import java.io.File; import java.util.List; import org.dom4j.Document; ...

  10. Maven 建立的项目resource对应的实际位置

        如图,springmvc-servlet.xml在项目中实际位置为: WEB-INF/classes/config/springmvc/springmvc-servlet.xml   在配置项 ...