10个小技巧让你的代码更Pythonic

作者|开鑫金服-朱文靖(python达人)

编辑|哧溜君

 

640?wx_fmt=jpeg&tp=webp&wxfrom=5&wx_lazy=1

 

Python 是一门兼具简单与功能强大的编程语言,拥有丰富的第三方库,在数据分析、AI、机器学习、Web 开发、运维、测试等多个领域都有不俗的表现。Python界中有一句非常有名的口号——人生苦短,我用Python。

 

假如要交换变量a和b的值,你会怎么做?

...

...

...

是这样吗?

a = 1

b = 2

temp = a

a = b

b = temp

隔壁的靖神觉得low爆了,竟然还用了多余的变量?

其实有更Pythonic的做法

a = 1

b = 2

a, b = b, a

 

640?wx_fmt=gif&tp=webp&wxfrom=5&wx_lazy=1

Pythonic是什么?

640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1

 

所谓Pythonic简单说就是用Python的特有的语法去实现相应的功能,使代码更简洁、优雅、通俗易懂,更重要的是,看上去(diao)堡了。下面就教你如何使用正确的姿势。

 

640?wx_fmt=gif&tp=webp&wxfrom=5&wx_lazy=1

如何让你的代码更

Pythonic?

640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1

 

1、遵循Python PEP8代码规范

 

这里只想说,驼峰式命名以经深入骨髓,不是说Python不支持这样的格式,只是使用带有PEP8插件的工具有助于你养成良好编码规范,更符合大部分用户的习惯,比如:

def  helloWorld():

       outputMessage = "Hello World"

       print outputMessage

PEP8代码规范:

def  hello_world():

       output_message = "Hello World"

       print output_message

 

2、用全局变量__file__实时获取当前文件夹和文件名

 

# 获取当前文件路径

print __file__ 

# 获取当前文件夹名称

print os.path.basename(__file__)  

# 获取当前文件夹的目录

print os.path.join(os.path.dirname(__file__))  

# 获取当前文件夹的上一层目录

print os.path.join(os.path.dirname(os.path.dirname(__file__))) 

 

3、动态加入PYTHONPATH

 

PYTHONPATH是python搜索模块路径集,有时自已写了一些模块执行时会报错no module named XXX,这就是python找不到此模块,此时我们可以动态的将目录加入到PYTHONPATH当中,这样即使分享代码给别人用,也能正常执行。

 

# 将当前文件夹实时加入到PYTHONPATH当中

sys.path.append(os.getcwd())

print sys.path

 

4、使用xrange代替range处理大文档

 

迭代器并不像list一样,直接存储进内存,想想处理一个1G文档的情况。

type_iterator = xrange(10)

type_list = range(10)

 

print type(type_iterator)  # 返回的是迭代器

print type(type_list)  # 返回的是list

 

5、使用列表推倒式获取文件

 

假如想获取当前目录下的文件,不考虑子文件夹的内容,通常可能这么做:

file_list = list()

for item in os.listdir(r"/tmp"):

    if os.path.isfile(item):

        file_list.append(item)

print file_list

而用列表推倒式一行就搞定了:

file_list = [item for item in os.listdir(r"/tmp") if os.path.isfile(item)]

print file_list 

 

6、使用enumerate获取对象索引和元素

 

为了同时获取一个可迭代对象的索引和元素,通常做法:

a_list = [1, 2, 3, 4]

for i in xrange(len(a_list)):

    print i, a_list[i]

使用enumerate时:

a_list = [1, 2, 3, 4]

for i, item in enumerate(a_list):

    print i, item

 

7、使用join拼接字符串

 

平时我们可能需要写入一个csv,标题是通过逗号分割,标题元素存在一个list当中。通常做法:

head_list = ["username", "password", "email"]

head_str = ""

for item in head_list:

    head_str += item + ","

print head_str

使用join时:

head_list = ["username", "password", "email"]

print ",".join(head_list)

 

8、多使用内置函数

 

尤其对列表进行一些计算时,如求和、最大值、最小值、排序等,以求合为例,通常是循环后累加:

a_list = [1, 10, 5, 7, 9]

total = 0

for item in a_list:

    total += item

print total

使用内置全局函数就简单多了:

from operator import mul

 

a_list = [1, 10, 5, 7, 9]

print sum(a_list)

print max(a_list)

print min(a_list)

print reduce(mul, a_list)  # list中所有元素相乘

print sorted(a_list)  # 简单的从小到大排序

 

9、使用模板方式格式化字符串

 

通常做法:

print "Life is Short , Please Use %s -- %s" % ("Python", "Bruce Eckel")

使用format,位置参数时:

print "Life is Short , Please Use {0} -- {1}".format("Python", "Bruce Eckel")

前两种方式来看,%s和使用占位符都不是那么清晰,而通过模板的方式就非常明了了:

print "Life is Short , Please Use {language} -- {name}".format(language="Python", name="Bruce Eckel")

 

10、用装饰器简化代码

 

装饰器并不算是Python特有的功能,其他语言也存在,使用得当可以大幅度减少重复性代码。假设我们想看某些方法到底运行了多少时间,总不能每一个方法都获取一个start_time、end_time,再相减得到运行时间吧。

import time

 

def  time_cost(func):

    def  wrapper(*args, **kwargs):

          start_time = time.time()

          func(*args, **kwargs)

          end_time = time.time()

          print "TIME COST:" + str(end_time - start_time)

    return wrapper

通过装饰器可以在任何一个函数上获取其执行的时间,而不会修改原函数执行的逻辑:

@time_cost

def  test_decorator():

      count = 0

      for in xrange(10000000):

          count += i

      print count

 

 

好了,通过几个简单的例子,有没有一种使用Python新姿势的感觉,后续我们会介绍更多Pythonic的技巧,大家拭目以待。

 

python彩蛋:python之禅,进入python窗口后输入import this

>>> import this

The Zen of Python, by Tim Peters

 

Beautiful 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!

翻译如下(摘自互联网):

 

优美胜于丑陋(python 以编写优美的代码为目标)

明了胜于晦涩(优美的代码应该是明了的,命名规范,风格相似)

简洁胜于复杂(优美的代码应当是简洁的,不要有复杂的内部实现)

复杂胜于凌乱(如果复杂不可避免。那代码间也不能有难懂的关系,要保持接口简洁)

扁平胜于嵌套(优美的代码应当是扁平的,不能有太多的嵌套)

间隔胜于紧凑(优美的代码有适当的间隔,不要奢望一行代码解决问题)

可读性很重要(优美的代码可读的)

即便假借5特例的实用性之名,也不可违背这些规则(这些规则 至高无上)

不要包容所有错误,除非你确定需要这样做(精确地捕获异常,不写 

except:pass 风格的代码)

当存在多种可能,不要尝试去猜测

而是尽量找一种,最好是唯一一种明显的解决方案(如果不确定,就用穷举法)

虽然这也不容易,因为你不是python之父(这里的dutch是指guido)

做也许好过不做,但不假思索就动手还不如不做(动手之前要细思量)

如果你无法向人描述你的方案,那肯定不是一个好方案;反之亦然(方案评测标准)

命名空间是一种绝妙的理念,我们应当多加利用(倡导与号召)

 

推荐阅读:

1、高智商人类,来挑战下小学题目吧!

2、MBT-模型驱动测试的探索与实践(一)

3、迄今为止最接地气的区块链应用,没有之一!

4、Elasticsearch依赖Guava类库冲突的解决方案

5、知识是一种概率

 

 

关注公众号↓,第一时间获取下期信息

 

640?wx_fmt=jpeg&tp=webp&wxfrom=5&wx_lazy=1

转载于:https://my.oschina.net/u/2969787/blog/1816245

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值