我们都喜欢 Python,因为它让编程和理解变的更为简单。但是一不小心,我们就会忽略规则,以非 Pythonic 方式编写一堆垃圾代码,从而浪费 Python 这个出色的语言赋予我们的优雅。Python 的代码风格是非常优雅、明确和简单,在 Python 解释器中执行 import this 你可以看到 Tim Peters 编写的 Python 之禅:

>>> import this
The Zen of Python, by Tim PetersBeautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

这里我找了目前最好的中文版本:

美 优于 丑

明确 优于 隐晦

简单 优于 复杂

复杂 也好过 繁复

扁平 优于 嵌套

稀疏 优于 拥挤

可读性很重要

固然代码实用与否 比洁癖更重要,

我们以为的特例也往往没有特殊到必须打破上述规则的程度

除非刻意地静默,否则不要无故忽视异常

如果遇到模棱两可的逻辑,请不要自作聪明地瞎猜。

应该提供一种,且最好只提供一种,一目了然的解决方案

当然这是没法一蹴而就的,除非你是荷兰人[1]

固然,立刻着手 好过 永远不做。

然而,永远不做 也好过 不审慎思考一撸袖子就莽着干

如果你的实现很难解释,它就一定不是个好主意

即使你的实现简单到爆,它也有可能是个好办法

命名空间大法好,不搞不是地球人!

[1]:本文作者 Tim peters 解释说这里的荷兰人指的是 Python 的作者 Guido van Rossum.

以下是用 Python 编写更好的代码的 8 种方法:

一、忘掉类 C 语言风格

如果需要打印列表中的所有元素及其索引,你想到的第一件事是:

for i in range(len(arr)):print(i, arr[i])

那么你仍然在编写 C 代码。摆脱这一点,请牢记 Python 关键字 enumerate 。它索引列表/字符串中的所有元素,并且支持设置索引的起始编号

>>> for index, item in enumerate(['a','b','c']):
...     print(index, item)
...
0 a
1 b
2 c
>>> for index, item in enumerate(['a','b','c'],1): #这里第二个参数可以设置起始编号
...     print(index,item)
...
1 a
2 b
3 c

现在看起来更好了,而且更加 Pythonic。将列表转换成字符串呢?如果你这样写:

# The C way
string = ''
for i in arr:string += i

就是 C 风格,如果使用 Python 的关键字 join,不仅效率更高,而且更优雅:

# The Python way
string = ''.join(arr)

就像 join 一样  ,Python 有很多神奇的关键字,因此请不要为语言工作,而是使用该语言为你工作。

二、牢记 PEP8

我不是要求你完全遵循 PEP8,而是要求遵循其中的大多数规则,何况现在有很多自动格式化的工具,足以让你的代码更加美观,我们的 Python 之父也说过:阅读代码的频率远远高于写代码的频率,他是如此的正确!因此代码的可读性非常重要。

你是否对自己曾经写过的代码感到好奇?为什么这么写,这句话为什么在这?好吧,PEP8 是大多数这类问题的答案。尽管代码注释是个好方法,但是代码的风格也需要加以调整,比如变量 i , j , count 等即使第一次出现时写了注释,也不能保证后面你仍然记得住,这样来看就浪费了宝贵的时间。

任何普通的程序员都可以编写计算机可以理解的代码。只有好的程序员可以编写人类可以理解的代码。

首选 CamelCase 作为类, UPPER_WITH_UNDERSCORES 作为常量,而 lower_with_underscores 作为变量,方法和模块名称。即使使用,也要避免使用单一名称功能 lambda 。

三、善用推导式

常用的推导式有:列表推导式,集合推导式,字典推导式。先说下列表推导式。

列表推导式就是当我们需要基于一个已有的列表创建新的列表时,所使用的语法格式,列表推导式包含以下四个部分:

1、一个输入序列(Input Sequence) 2、一个变量,代表着输入序列的一个成员(Variable) 3、一个可选的判定表达式,表达这个变量满足的条件(Optional Predicate ) 4、一个输出序列,根据 2 和 3 生成一个输出序列(Output Expression)

比如有个列表既有数字,又有字符,现在需要计算数字的平方,并将结果放在新的列表中,如果不用列表推导式,写出的代码就是这样的:

# bad code
a_list = [1, ‘4’, 9, ‘a’, 0, 4]squared_ints = []
for item in a_list:if type(item) == types.IntType:squared_ints.append(item**2)

如果使用列表推导式,只需要两行代码,非常的优雅:

a_list = [1, ‘4’, 9, ‘a’, 0, 4]
squared_ints = [ e**2 for e in a_list if type(e) == types.IntType ]

当然,如果你喜欢 map 和 filter,你还可以这样做,当时这是不推荐的,因为可读性不好:

map(lambda e: e**2, filter(lambda e: type(e) == types.IntType, a_list))

比如集合推导式的使用:

给定输入

names = [ 'Bob', 'JOHN', 'alice', 'bob', 'ALICE', 'J', 'Bob' ]

希望得到:

{ 'Bob', 'John', 'Alice' }

那么集合推导式就是:

{ name[0].upper() + name[1:].lower() for name in names if len(name) > 1 }

再比如字典推导式:

mcase = {'a':10, 'b': 34, 'A': 7, 'Z':3}mcase_frequency = { k.lower() : mcase.get(k.lower(), 0) + mcase.get(k.upper(), 0) for k in mcase.keys() }# mcase_frequency == {'a': 17, 'z': 3, 'b': 34}

从上面可以看出。推导式风格的代码是优雅的,人类易读的。

四、你还在显式的关闭文件吗?

如果你在写代码时仍然在显式的关闭文件,就像上图中的 programmer,你在为编程语言工作,如果你学会了使用 with 上下文管理器,那么你就是一个 Python programmer,让编程语言为你工作:

with open('filename.txt', 'w') as filename:filename.write('Hello')

当程序退出 with 块时,文件会自动关闭。with 语句的语法格式:

with VAR as EXPR:BLOCK

相当于:

mgr = (EXPR)
exit = type(mgr).__exit__  # Not calling it yet
value = type(mgr).__enter__(mgr)
exc = True
try:try:VAR = value  # Only if "as VAR" is presentBLOCKexcept:# The exceptional case is handled hereexc = Falseif not exit(mgr, *sys.exc_info()):raise# The exception is swallowed if exit() returns true
finally:# The normal and non-local-goto cases are handled hereif exc:exit(mgr, None, None, None)

有很多网络连接、数据库连接库都会提供 with 功能。甚至熟悉了 with 的实现机制后,可以自行实现 with 功能:

class File(object):def __init__(self, file_name, method):self.file_obj = open(file_name, method)def __enter__(self):return self.file_objdef __exit__(self, type, value, traceback):self.file_obj.close()

只要定义了 __enter__,__exit__方法,就可以使用 with 语句:

with File('demo.txt', 'w') as opened_file:opened_file.write('Hola!')

五、使用迭代器和生成器

迭代器:iterator 生成器:generator

迭代器和生成器都是 Python 中功能强大的工具,值得精通。迭代器是一个更笼统的概念:任何一个对象只要它所属的类具有__next__方法(Python 2是next)和具有返回 self 的__iter__方法都是迭代器。

每个生成器都是一个迭代器,但反之不然。生成器是通过调用具有一个或多个 yield 表达式的函数而构建的,并且该函数是满足上一段对iterator 的定义的对象。

使用区别:

网络上很多技术博主都说生成器是懒人版的迭代器,比迭代器更节省内存,其实是错误的,他们都很节省内存(我会举例子)。

他们真正的区别是:当你需要一个具有某些复杂的状态维护行为的类,或者想要公开除__next__(和__iter____init__)之外的其他方法时,你就需要自定义迭代器,而不是生成器。

通常,一个生成器(有时,对于足够简单的需求,一个生成器表达式)就足够了,并且它更容易编写代码。

比如说计算正整数 a 到 b (b 远远大于 a)直接的平方,生成器的话就是:

def squares(start, stop):for i in range(start, stop):yield i * igenerator = squares(a, b)

或者:

generator = (i*i for i in range(a, b))

如果是迭代器,则是这样:

class Squares(object):def __init__(self, start, stop):self.start = startself.stop = stopdef __iter__(self): return selfdef __next__(self): # next in Python 2if self.start >= self.stop:raise StopIterationcurrent = self.start * self.startself.start += 1return currentiterator = Squares(a, b)

可以看出,迭代器写起来稍麻烦,当也更为灵活,比如你想提供一个 current 方法时,可以直接添加到 Squares 类中:

    def current(self):return self.start

从上述可以看出,迭代器并没有保存 a 到 b 之间的所有值,所有并不消耗过多的内存,这一点也可以自行测试,代码如下:

>>> from collections.abc import Iterator
>>> from sys import getsizeof
>>> a = [i for i in range(1001)]
>>> print(type(a))
<class 'list'>
>>> print(getsizeof(a))
9016
>>>
>>> b = iter(a)
>>> print(type(b))
<class 'list_iterator'>
>>> print(isinstance(b,Iterator))
True
>>> print(getsizeof(b))
48
>>> c = (i for i in range(1001))
>>> print(getsizeof(b))
48
>>> type(c)
<class 'generator'>
>>> type(b)
<class 'list_iterator'>

可以看出 b 是 iterator,c 是 generator,它们占用的内存大小是一样的。

六、善用 itertools

itertools 模块标准化了一个快速、高效利用内存的核心工具集,这些工具本身或组合都很有用。它们一起形成了“迭代器代数”,这使得在纯 Python 中有可以创建简洁又高效的专用工具。比如,如果你想要字符串中所有字符的组合或列表中数字的所有组合,则只需编写

from itertools import combinations
names = 'ABC'
for combination in combinations(names, 2):print(combination)
''' Output -('A', 'B')('A', 'C')('B', 'C')
'''

这是一个值得经常使用的标准库,更多详细功能请参考官方文档:https://docs.python.org/zh-cn/3/library/itertools.html[1]

七、善用 collections

这又是一个值得使用的标准库 collections,它提供替代内置的数据类型的多个容器,如 defaultdict、OrderedDict、namedtuple、Counter、deque 等,非常使用,而且比自己实现要安全稳定的多。比如:

# frequency of all characters in a string in sorted order
from collections import (OrderedDict, Counter)
string = 'abcbcaaba'
freq = Counter(string)
freq_sorted = OrderedDict(freq.most_common())
for key, val in freq_sorted.items():print(key, val)
''' Output -('a', 4)('b', 3)('c', 2)
'''

不多说了,看官方文档:https://docs.python.org/3/library/collections.html[2]

八、不要过度使用类

不要过度使用类。坚持用 Java 和 C ++ 的程序员会经常使用类,但是在使用 Python 时,可以在函数和模块的帮助下复用代码。除非绝对需要,否则不必创建类。

本文讲述类 8 个让你写出更好 Python 代码的方法,希望对你有所帮助。

推荐阅读:

10个技巧让你的代码更优雅

6 个值得玩味的 Python 代码

参考资料

[1]

https://docs.python.org/zh-cn/3/library/itertools.html: https://docs.python.org/zh-cn/3/library/itertools.html

[2]

https://docs.python.org/3/library/collections.html: https://docs.python.org/3/library/collections.html

如何写出更具有Python风格的代码相关推荐

  1. python代码怎么写出色_如何写出更具有Python风格的代码,五分钟教会你!

    我们都喜欢 Python,因为它让编程和理解变的更为简单.但是一不小心,我们就会忽略规则,以非 Pythonic 方式编写一堆垃圾代码,从而浪费 Python 这个出色的语言赋予我们的优雅.Pytho ...

  2. python优雅代码大全_10个Python技巧帮你写出更优雅的代码

    阅读本文需要 2 分钟,公众号 somenzz ,欢迎学习 Python 的朋友订阅. 现在写代码的门槛非常低了,少儿都开始编程了,但从代码的风格一眼看出编码水平.是的,写代码是容易的,写出易读的代码 ...

  3. python写出的程序如何给别人使用-涨姿势!这些小技巧让小白也可以写出更优雅的Python代码!...

    原标题:涨姿势!这些小技巧让小白也可以写出更优雅的Python代码! 一.前言 我前两天回答了两个Python相关的问题,收到了很多赞,从答案被收藏的情况来看,确实对不少人都很有帮助,所以我也很开心. ...

  4. Python拾珍:用这些功能写出更简洁、更可读或更高效的代码

    本章我会带领大家回顾那些遗漏的地方.Python提供了不少并不是完全必需的功能(不用它们也能写出好代码),但有时候,使用这些功能可以写出更简洁.更可读或者更高效的代码,甚至有时候三者兼得. 19.1 ...

  5. 【整洁之道】如何写出更整洁的代码(上)

    如何写出更整洁的代码 代码整洁之道不是银弹,不会立竿见影的带来收益. 没有任何犀利的武功招式,只有一些我个人异常推崇的代码整洁之道的内功心法.它不会直接有效的提高你写代码的能力与速度,但是对于程序员的 ...

  6. 5个小技巧让你写出更好的 JavaScript 条件语句

    在使用 JavaScript 时,我们常常要写不少的条件语句.这里有五个小技巧,可以让你写出更干净.漂亮的条件语句. 1.使用 Array.includes 来处理多重条件 举个栗子 : // 条件语 ...

  7. 5个小技巧让你写出更好的JavaScript 条件语句

    在使用 JavaScript 时,我们常常要写不少的条件语句.这里有五个小技巧,可以让你写出更干净.漂亮的条件语句. 使用 Array.includes 来处理多重条件 举个栗子 : // 条件语句 ...

  8. 大佬教你如何写出更好的CSS,分享web前端资料

    让我们开门见山:编写优秀的 CSS 代码是件十分痛苦的事情.很多开发人员都不想做 CSS 开发.你让我干什么都行,但是 CSS 还是算了吧. 在我创建应用的时候,从来都无法从 CSS 中享受到乐趣.但 ...

  9. 用集合return多个值_Python拾珍:用这些功能写出更简洁、更可读或更高效的代码

    本章我会带领大家回顾那些遗漏的地方.Python提供了不少并不是完全必需的功能(不用它们也能写出好代码),但有时候,使用这些功能可以写出更简洁.更可读或者更高效的代码,甚至有时候三者兼得. 19.1 ...

最新文章

  1. P2396 yyy loves Maths VII 状压dp 变态卡常
  2. 4 Ways to Make Sure You Always Have Something to Say Online
  3. c语言变量申明和定义区别,C语言中变量定义与声明的区别
  4. CANN5.0黑科技解密 | 别眨眼,缩小隧道,让你的AI模型“身轻如燕”
  5. android命名管道创建使用
  6. 高级 Java 程序员都在学什么?
  7. php 不懂英文symfony2,请问symfony2一些使用心得
  8. 小程序wxParse
  9. 基于jsp、ssm企业工资管理系统
  10. 脑洞大开!把 14 亿中国人拉到一个微信群 ?
  11. 健康驿站房间线上预约系统网站分析
  12. 【SeedCoder2015年 热身题5 搜索】上上下下ABAB (题目+答案)
  13. Apache Shiro 认证绕过漏洞(CVE-2020-1957)
  14. 解决‘WebDriver‘ object has no attribute ‘find_element_by_xpath‘问题
  15. python读取excel文本单元格换行符_Excel自文本导入内容时如何做到单元格内换行...
  16. ES GEO地理空间查询java版
  17. java可视化界面背景图_Java界面:java设置背景图片
  18. matlab 相场法,晶体相场法模拟.pdf
  19. 光伏并网逆变器,F28335光伏并网逆变器
  20. 【零基础学WebGL】矩阵变换

热门文章

  1. 【赖世雄音标】——元音
  2. swal()弹出删除确认框
  3. 架构测试:HAproxy实现负载均衡,前端为nginx+php,数据库实现读写分离和高可用...
  4. SQL-按日期不间断统计
  5. 爬取静态壁纸网站实现批量下载
  6. phpMyadmin /scripts/setup.php Execute Arbitrary PHP Code Via A Crafted POST Request CVE-2010-3055
  7. Stata:一文读懂事件研究法EventStudy
  8. GBase 8c技术特点
  9. Bootstrap+web+Idea实现登录页面(含验证码)
  10. CLAHE算法代码详解