设为首页收藏本站

Crossin的编程教室

 找回密码
 立即加入
查看: 7013|回复: 0
打印 上一主题 下一主题

对比几段代码,看看你是 Python 菜鸟还是老鸟

[复制链接]

169

主题

1

好友

733

积分

版主

Rank: 7Rank: 7Rank: 7

跳转到指定楼层
楼主
发表于 2019-3-1 17:06:33 |只看该作者 |倒序浏览

Python 里有个小彩蛋:

在 Python Shell 里输入 import this

这段话被称作“Python 之禅”(The Zen of Python),它列举了一些 Python 所推崇的理念,比如:
优美胜于丑陋明确胜于隐晦简单胜于复杂…可读性很重要不要忽略错误面对不确定时,拒绝猜测现在做好过不做,但盲目动手不如不做如果你的实现很难说清楚,那是个坏想法;反之亦然…
当你学完基础,可以写点代码的时候,可能经常感觉自己的实现很别扭。有经验的程序员会一眼看出你的代码出自一个初学者之手。这就是我们经常说的,代码不够 pythonic。

所谓 pythonic,我觉得包含两方面:一是代码的风格符合 Python 的特点,能合理使用 Python 的“语法糖”;二是代码简洁优美,稳定性高,可读性好,便于维护和修改。所谓“Python 之禅”并不仅限于 Python,很多理念是编程普适的。

比如来实现对一个列表中元素的遍历访问,我见过很多次有人这么写:
  1. for i in range(len(lst)):
  2.     print(lst[i])
复制代码
这样的同学很可能是之前有过 C/C++ 或 Java 的经验。这么写功能上没问题,但不够简洁,不够 pythonic。更好的实现方式:
  1. for i in lst:
  2.     print(i)
复制代码
这种不影响功能,但能简化程序、提高可读性的语法,我们称之为“语法糖”(Syntactic sugar)。Python 中类似的例子还有不少,来举几个:

1、交换两个变量的值,普通写法:
  1. temp = a
  2. a = b
  3. b = temp
复制代码
pythonic 写法:
  1. a, b = b, a
复制代码
2、类似的解包(unpacking)用法还可以实现多个返回值的函数。普通写法:
  1. def func(a, b):
  2.     result = [b, a]
  3.     return result
  4. r = func(a, b)
  5. x = r[0]
  6. y = r[1]
复制代码
pythonic 写法:
  1. def func(a, b):
  2.     return b, a
  3. x, y = func(a, b)
复制代码
3、读写文件,普通写法:
  1. f = open('filename.txt')
  2. text = f.read()
  3. print(text)
  4. f.close()
复制代码
pythonic 写法:
  1. with open('filename.txt') as f:
  2.     for line in f:
  3.         print(line)
复制代码
with 的好处是即使出错,也会帮你关闭文件。

4、拼接字符串,普通写法:
  1. letters = ['h', 'e', 'l', 'l', 'o']
  2. s = ''
  3. for l in letters:
  4.     s += l
  5. print(s)
复制代码
pythonic 写法:
  1. print(''.join(letters))
复制代码
5、关于前面遍历列表的例子,如果你想带上索引,可以这么写:
  1. for i, elem in enumerate(lst):
  2.     print(i, elem)
复制代码
遍历字典项:
  1. for key, value in dct.items():
  2.     print(key, value)
复制代码
6、取出列表中大于 0 的元素,生成新列表。普通写法:
  1. new_lst = []
  2. for i in lst:
  3.     if i > 0:
  4.         new_lst.append(i)
复制代码
pythonic 写法:
  1. new_lst = [i for i in lst if i > 0]
复制代码
这个被称为“列表解析式”(List comprehension,中文翻译说法有很多),可以说是非常 pythonic 的一个用法了。

更进一步,如果数据量很大,而你对新列表仅仅是遍历操作,并不需要一个列表对象,可以采用生成器:
  1. new_lst = (i for i in lst if i > 0)
  2. for i in new_lst:
  3.     print(i)
复制代码
这样会更节省资源,提升执行效率。

7、判断一个值是否为True、是否为空列表、是否是None,普通写法:
  1. if x == True:
  2.     pass
  3. if len(y) == 0:
  4.     pass
  5. if z == None:
  6.     pass
复制代码
pythonic 写法:
  1. if x:
  2.     pass
  3. if not y:
  4.     pass
  5. if z is None:
  6.     pass
复制代码
8、根据键名获取字典中对应的值,普通写法:
  1. value = dct[key]
复制代码
这样的问题在于,如果 key 不存在,代码就报错跳出。于是你不得不增加更多的判断。

pythonic 写法:
  1. value = dct.get(key, 0)
复制代码
改用 get 方法,不存在时会得到 None,或者指定的默认值(这里是 0)。

篇幅所限,以上仅仅是一些比较具有代表性的例子。但凡事要有度,过分追求 pythonic 的写法也可能导致代码的可读性下降。比如有人喜欢把很多功能写在一个语句中,这反倒不 pythonic 了。所以,我们需要有一些设计的原则,但又不必拘泥于具体的形式,否则就钻入牛角尖了。

那么对于学习者来说,如何才能写出更 pythonic 的代码呢?说到底还是个经验积累的过程,菜鸟不可能看本书、上个课就一夜变成老鸟,但只要坚持得够久就可以。我这边给几个建议:
多看。看官方库、优秀项目,学习别人的代码。以及看一些优质的教程和经验分享,比如 Crossin的编程教室多搜。当你实现一个小功能后,去网上搜一下,别人是怎么写的,对比下是不是比你自己的更好。举个例子:如何从列表中删除重复元素。你自己可以通过循环实现,但只要搜一下,就会知道 list(set(x)) 这种用法。多写。自己还没写几行代码,就先别纠结什么效率什么风格了。最终还是要写上足够量的代码,才会有“悟道”的那一刻。
另外,对于代码本身,Python 有一套书写规范,叫做 PEP8。里面约定了很多细节,比如哪里该空格、注释怎么写、什么地方该换行、如何命名等等。链接:https://www.python.org/dev/peps/pep-0008/,网上还有翻译好的中文版,务必找时间看一看。

最后,留2个小作业:
1. 判断一个列表 A 是否为另一个列表 B 的“子集”,也就是列表 A 中的元素是否都在列表 B 中。2. 计算 1 加到 100 的和。尽可能写出你认为 pythonic 的代码。

════

其他文章及回答:

学编程:如何自学Python | 新手引导 | 一图学Python

开发案例:智能防挡弹幕 | 红包提醒 | 流浪地球

欢迎搜索及关注:Crossin的编程教室





回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即加入

QQ|手机版|Archiver|Crossin的编程教室 ( 苏ICP备15063769号  

GMT+8, 2024-4-20 10:49 , Processed in 0.016299 second(s), 22 queries .

Powered by Discuz! X2.5

© 2001-2012 Comsenz Inc.

回顶部