何为pythonic?

pythonic如果翻译成中文的话就是很python。很+名词结构的用法在中国不少,比如:很娘,很国足,很CCTV等等。

我的理解为,很+名词表达了一种特殊和强调的意味。所以很python可以理解为:只有python能做到的,区别于其他语言的写法,其实就是python的惯用和特有写法。

举个例子:

很python的写法:

a,b = b,a

不python的写法:

temp = a
a = b
b = temp

上面的例子通过了元组的pack和unpack完成了对a,b的互换,避免了使用临时变量temp,而且只用了一行代码。

以下为了简略,我们用P表示pythonic的写法,NP表示non-pythonic的写法,当然此P-NP非彼P-NP。

为什么要追求pythonic?

相比于NP,P的写法简练,明确,优雅,绝大部分时候执行效率高,代码越少也就越不容易出错。我认为好的程序员在写代码时,应该追求代码的正确性,简洁性和可读性,这恰恰就是pythonic的精神所在。

对于具有其他编程语言经验而初涉Python的程序员(比如我自己)来说,在写Python代码时,认识到pythonic的写法,会带来更多的便利和高效,而本文的主要读者也将是这群程序员。

以下将给出P和NP的n种示例,供读者和自己参考,查阅。

本文最后会列出参考资料,这些参考资料在我看来都极具价值。

P vs. NP的示例

链式比较

P:

1
2
3
4
a = 3
b = 1 1 <= b <= a < 10
# True

NP:

b >= 1 and b <= a and a < 10
# True

P是小学生都能看懂的语法,简单直接省代码~

真值测试

P:

name = 'Tim'
langs = ['AS3', 'Lua', 'C']
info = {'name': 'Tim', 'sex': 'Male', 'age':23 } if name and langs and info:
print('All True!') #All True!

NP:

if name != '' and len(langs) > 0 and info != {}:
print('All True!') #All True!

简而言之,P的写法就是对于任意对象,直接判断其真假,无需写判断条件,这样既能保证正确性,又能减少代码量。

真假值表(记住了假你就能省很多代码!)

True False
任意非空字符串 空的字符串 ''
任意非0数字 数字0
任意非空容器 空的容器 [] () {} set()
其他任意非False None

contains and iteration

P:

name = 'Safe Hammad'
if 'H' in name:
print('This name has an H in it!') pets = ['Dog', 'Cat', 'Hamster']
for pet in pets:
print('A', pet, 'can be very cute!')

NP:

name = 'Safe Hammad'
if name.find('H') != -1:
print('This name has an H in it!') pets = ['Dog', 'Cat', 'Hamster']
i = 0
while i < len(pets):
print('A', pets[i], 'can be very cute!')
i += 1

contains 可以用于 lists, dicts (keys), sets, strings

还可以用于已实现 contains 方法的类

字符串反转

P:

def reverse_str( s ):
return s[::-1]

NP:

def reverse_str( s ):
t = ''
for x in xrange(len(s)-1,-1,-1):
t += s[x]
return t

P的写法简单,经测试,效率也更好。

如果用于检测回文,就是一句话input == input[::-1],多么的优雅!

字符串列表的连接

P:

strList = ["Python", "is", "good"]  

res =  ' '.join(strList)
# Python is good

NP:

res = ''
for s in strList:
res += s + ' '
# Python is good
# 最后还有个多余空格

string.join()常用于连接列表里的字符串,相对于NP,P的方式十分高效,且不会犯错。

EAFP优于LBYL

EAFP: It's Easier to Ask for Forgiveness than

Permission.

LBYL: Look Before You Leap

P:

d = {'x': '5'}
try:
value = int(d['x'])
except (KeyError, TypeError, ValueError):
value = None

NP:

d = {'x': '5'}
if 'x' in d and \
isinstance(d['x'], str) and \
d['x'].isdigit():
value = int(d['x'])
else:
value = None

python抛出异常并不像java那样代价非常昂贵

列表求和,最大值,最小值,乘积

P:

numList = [1,2,3,4,5]   

sum = sum(numList)  #sum = 15
maxNum = max(numList) #maxNum = 5
minNum = min(numList) #minNum = 1
from operator import mul
prod = reduce(mul, numList, 1) #prod = 120 默认值传1以防空列表报错

NP:

sum = 0
maxNum = -float('inf')
minNum = float('inf')
prod = 1
for num in numList:
if num > maxNum:
maxNum = num
if num < minNum:
minNum = num
sum += num
prod *= num
# sum = 15 maxNum = 5 minNum = 1 prod = 120

经简单测试,在numList的长度为10000000时,在我的机器上对列表求和,P耗时0.6s,NP耗时1.3s,将近两倍的差距。所以不要自己造轮子了。

列表推导式

P:

l = [x*x for x in range(10) if x % 3 == 0]
# l = [0, 9, 36, 81]

NP:

l = []
for x in range(10):
if x % 3 == 0:
l.append(x*x)
# l = [0, 9, 36, 81]

你看,使用P的列表推导式,构建新列表变得多么简单直观!

字典的默认值

P:

dic = {'name':'Tim', 'age':23}  

dic['workage'] = dic.get('workage',0) + 1
# dic = {'age': 23, 'workage': 1, 'name': 'Tim'}

NP:

if 'workage' in dic:
dic['workage'] += 1
else:
dic['workage'] = 1
# dic = {'age': 23, 'workage': 1, 'name': 'Tim'}

dict的get(key,default)方法用于获取字典中key的值,若不存在该key,则将key赋默认值default。

P相比NP的写法少了if...else...,实乃痛恨if...else...之人首选!

for…else…语句

P:

for x in xrange(1,5):
if x == 5:
print 'find 5'
break
else:
print 'can not find 5!'
# can not find 5!

NP:

find = False
for x in xrange(1,5):
if x == 5:
find = True
print 'find 5'
break
if not find:
print 'can not find 5!'
# can not find 5!

for...else...的else部分用来处理没有从for循环中断的情况。有了它,我们不用设置状态变量来检查是否for循环有break出来,简单方便。

三元符的替代

P:

a = 3   

b = 2 if a > 2 else 1
# b = 2

NP:

if a > 2:
b = 2
else:
b = 1
# b = 2

如果你具备C的编程经验,你就会寻找A ? B : C的替代品。你可能发现A and B or C看起来还不错,但是b = a > 1 and False or True会返回True,而实际意图应该返回False。

使用b = False if a > 1 else True则会正确返回False,所以它才是正宗的三元符替代品。

Enumerate

P:

array = [1, 2, 3, 4, 5]

for i, e in enumerate(array,0):
print i, e
#0 1
#1 2
#2 3
#3 4
#4 5

NP:

for i in xrange(len(array)):
print i, array[i]
#0 1
#1 2
#2 3
#3 4
#4 5

使用enumerate可以一次性将索引和值取出,避免使用索引来取值,而且enumerate的第二个参数可以调整索引下标的起始位置,默认为0。

使用zip创建键值对

P:

keys = ['Name', 'Sex', 'Age']
values = ['Tim', 'Male', 23] dic = dict(zip(keys, values))
# {'Age': 23, 'Name': 'Tim', 'Sex': 'Male'}

NP:

dic = {}
for i,e in enumerate(keys):
dic[e] = values[i]
# {'Age': 23, 'Name': 'Tim', 'Sex': 'Male'}

zip方法返回的是一个元组,用它来创建键值对,简单明了。

文件读取

P:

file = open("some_filename", "r")

while 1:   # infinite loop
line = file.readline()
if not line: # 'readline()' returns None at end of file.
break # Process the line.

NP:

file = open("some_filename", "r")

for line in file:
# Process the line.

pythonic-让python代码更高效的更多相关文章

  1. 可爱的豆子——使用Beans思想让Python代码更易维护

    title: 可爱的豆子--使用Beans思想让Python代码更易维护 toc: false comments: true date: 2016-06-19 21:43:33 tags: [Pyth ...

  2. 让 Python 代码更易维护的七种武器——代码风格(pylint、Flake8、Isort、Autopep8、Yapf、Black)测试覆盖率(Coverage)CI(JK)

    让 Python 代码更易维护的七种武器 2018/09/29 · 基础知识 · 武器 原文出处: Jeff Triplett   译文出处:linux中国-Hank Chow    检查你的代码的质 ...

  3. 让Python代码更快运行的 5 种方法

    不论什么语言,我们都需要注意性能优化问题,提高执行效率.选择了脚本语言就要忍受其速度,这句话在某种程度上说明了Python作为脚本语言的不足之处,那就是执行效率和性能不够亮.尽管Python从未如C和 ...

  4. 程序员需要掌握的七种 Python 代码更易维护的武器

    检查你的代码风格 PEP 8 是 Python 代码风格规范,它规定了类似行长度.缩进.多行表达式.变量命名约定等内容.尽管你的团队自身可能也会有稍微不同于 PEP 8 的代码风格规范,但任何代码风格 ...

  5. 写出pythonic的python代码

    http://www.cnblogs.com/dadadechengzi/p/6226071.html 1,列表推导(没当要对序列中的内容进行循环处理时,就应该尝试使用列表推倒) 在python中编写 ...

  6. Pycharm配置autopep8让Python代码更符合pep8规范

    一.何为pep8? PEP 8官方文档 -- Style Guide for Python Code PEP8中文翻译(转) 二.Pycharm中配置pep8 Pycharm本身是有pep8风格检测的 ...

  7. 学习 27 门编程语言的长处,提升你的 Python 代码水平

    Python猫注:Python 语言诞生 30 年了,如今的发展势头可谓如火如荼,这很大程度上得益于其易学易用的优秀设计,而不可否认的是,Python 从其它语言中偷师了不少.本文作者是一名资深的核心 ...

  8. 如何让你的Python代码更加pythonic ?

    pythonic如果翻译成中文的话就是很python.很+名词结构的用法在中国不少. 以下为了简略,我们用P表示pythonic的写法,NP表示non-pythonic的写法,当然此P-NP非彼P-N ...

  9. 让你的Python代码更加pythonic

    http://wuzhiwei.net/be_pythonic/ 何为pythonic? pythonic如果翻译成中文的话就是很python.很+名词结构的用法在中国不少,比如:很娘,很国足,很CC ...

随机推荐

  1. Python 与 C/C++ 交互的几种方式

    python作为一门脚本语言,其好处是语法简单,很多东西都已经封装好了,直接拿过来用就行,所以实现同样一个功能,用Python写要比用C/C++代码量会少得多.但是优点也必然也伴随着缺点(这是肯定的, ...

  2. Brief introduction to Java String Split 【简单介绍下Java String Split】

    Split is a common function in Java. It split a full string to an array based on delimeter. For examp ...

  3. 【Netty】Netty核心组件介绍

    一.前言 前篇博文体验了Netty的第一个示例,下面接着学习Netty的组件和其设计. 二.核心组件 2.1. Channel.EventLoop和ChannelFuture Netty中的核心组件包 ...

  4. 关于MAC设置免费的动态壁纸

    首先大部分的动态壁纸都是收费的或者是已经固定的,其实这一款也是固定的 但是这个固定的是可以进行修改的 第一先在App Store下载 LiveDesktop Pro  这一款是免费的 然后下载后进行打 ...

  5. 第一篇:使用Spark探索经典数据集MovieLens

    前言 MovieLens数据集包含多个用户对多部电影的评级数据,也包括电影元数据信息和用户属性信息. 这个数据集经常用来做推荐系统,机器学习算法的测试数据集.尤其在推荐系统领域,很多著名论文都是基于这 ...

  6. springcloud(五):熔断监控Hystrix Dashboard和Turbine

    Hystrix-dashboard是一款针对Hystrix进行实时监控的工具,通过Hystrix Dashboard我们可以在直观地看到各Hystrix Command的请求响应时间, 请求成功率等数 ...

  7. Swift和Javascript的神奇魔法

    Swift和Javascript的神奇魔法 记录Swift和Javascript如何进行交互 前言 今天在网上看到了一篇介绍Swift和Javascript交互的文章,感觉作者写的很好,因此把作者文章 ...

  8. 关于QT按键信号槽的总结(原创)

    QT界面按钮一般是必填的: 每个按钮都要 Go to slot 下面有几个都是常用的,先说一下 clicked:pressed:releaed的区别 字面意思看:click是点击一下,pressed是 ...

  9. (中级篇 NettyNIO编解码开发)第七章-java序列化

    相信大多数Java程序员接触到的第一种序列化或者编解码技术就是.Java的默认序列化,只需要序列化的POJO对象实现java.io.Serializable接口,根据实际情况生成序列ID,这个类就能够 ...

  10. 001---Hibernate简介( 开源O/R映射框架)

    该系列教程是使用hibernate3,hibernate4和3有区别(集成spring,使用等),请注意 001---Hibernate简介(开源O/R映射框架) ORM(Object Relatio ...