Pythonic 是什么意思?

论坛 期权论坛 工作     
匿名的论坛用户   2021-1-9 06:04   10962   5
分享到 :
0 人收藏

5 个回复

倒序浏览
2#
热心的小回应  16级独孤 | 2021-1-9 06:04:22 发帖IP地址来自
在我理解,Pythonic 就是很 Python 的 Python 代码。比如「这很社区」一般用来表示「社区社区特有的现象」,「这很百度」表示「百度公司特有的行为」,「很 Python 」的代码就是 「 Pythonic 」。也就是说,Python 很明显区别于其它语言的(优雅)写法。

比如,在 C-Like 语言中一般这样交换两个数字 a,b:
  1. int t = a;a = b;b = t
复制代码
而在 Python 中,一般这样写:
  1. a, b = b, a
复制代码
类似地,Python 一般这样判断数字在某个区间:
[code]0
3#
热心的小回应  16级独孤 | 2021-1-9 06:04:23 发帖IP地址来自
这是我在怎样才能写出pythonic的代码? - 程序员 这个问题下的答案,刚好可以用来回答这个问题,希望对大家有帮助。

首先,我们要回答什么是Pythonic?

我们先来看一下,Python程序员每天津津乐道的the zen of python(Python之禅)
  1. >>> import thisThe 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. 优美胜于丑陋明了胜于晦涩简介胜于复杂……可读性很重要……
复制代码
难道只有我一个人觉得这是正确的废话吗?难道只有我一个人觉得这是正确的废话吗?难道只有我一个人觉得这是正确的废话吗?

它只告诉你什么是好,什么是不好,但是,却没有告诉你通往成功彼岸的方法。从这个角度来说,我更推荐:




Pythonic一直以来都是只能意会,不能言传的东西,然而,为了帮助新同学理解,我准备给出确切的定义:Pythonic就是以Python的方式写出简洁优美的代码!

首先,不管用什么语言,你都应该努力写出简洁优美的代码,如果不能,那我推荐你看看《重构》和《代码整洁之道》,虽然这两本书使用的是java语言,但是,并不影响作者要传递的思想。

比如,我们知道,Python里面的字符串、列表和元组,都称之为序列,序列支持索引操作和切片操作,切片操作可以指定起点、终点和步长,步长也可以为负数。我们看下面的切片:
  1. L = [1, 2, 3, 4, 5, 6, 7, 8, 9]L[-2::-2]L[-2:2:-2]L[2:2:-2]
复制代码
谁能快速的回答我上面几个切片的答案?没有人!所以,Python也有很多语法,但是,并不能乱用。就这个例子来说:
  • 在同一个切片操作中,不要同时使用start、end和stride
  • 尽量使用stride为正数,且不要带start和end索引的切割操作
在你已经能够写出简洁优美的代码的前提下,要写出Pythonic的代码,还需要对Python的语言有比较好的了解。我举几个在Python里面与在C、C++和Java里面有显著差别的例子。


1. 交换两个数字

在其他语言里面
  1. t = aa = bb = t
复制代码
在Python语言里面
  1. a, b = b, a
复制代码
2. 列表推导

列表推导是C、C++、Java里面没有的语法,但是,是Python里面使用非常广泛,是特别推荐的用法。

与列表推导对应的,还有集合推导和字典推导。我们来演示一下。
  • 列表:30~40 所有偶数的平方
  1. [ i*i for i in range(30, 41) if i% 2 == 0 ]
复制代码
  • 集合:1~20所有奇数的平方的集合
  1. { i*i for i in range(1, 21) if i % 2 != 0 }
复制代码
  • 字典:30~40 所有奇数的平方
  1. { i:i*i for i in range(30, 40) if i% 2 != 0 }
复制代码
再举两个实用的例子:
  • 当前用户home目录下所有的文件列表
  1. [ item for item in os.listdir(os.path.expanduser('~')) if os.path.isfile(item) ]
复制代码
  • 当前用户home目录下所有的目录列表
  1. [ item for item in os.listdir(os.path.expanduser('~')) if os.path.isdir(item) ]
复制代码
  • 当前用户home目录下所有目录的目录名到绝对路径之间的字典
  1. { item: os.path.realpath(item) for item in os.listdir(os.path.expanduser('~')) if os.path.isdir(item) }
复制代码
3. 上线文管理器

我们要打开文件进行处理,在处理文件过程中可能会出错,但是,我们需要在处理文件出错的情况下,也顺利关闭文件。

Java风格/C++风格的Python代码:
  1. myfile= open(r'C:\misc\data.txt')try:    for line in myfile:        ...use line here...finally:    myfile.close()
复制代码
Pythonic的代码:
  1. with open(r'C:\misc\data.txt') as myfile:    for line in myfile:        ...use line here...
复制代码
这里要说的是,上下文管理器是Python里面比较推荐的方式,如果用try...finally而不用with,就会被认为不够Pythonic。此外,上线文管理器还可以应用于锁和其他很多类似必须需要关闭的地方。

4. 装饰器

装饰器并不是Python特有的,只是,在Python里面应用非常广泛,我们来看一个例子。

考虑这样一组函数,它们在被调用时需要对某些参数进行检查,在本例中,需要对用户名进行检查,以判断用户是否有相应的权限进行某些操作。
  1. class Store(object):    def get_food(self, username, food):        if username != 'admin':            raise Exception("This user is not allowed to get food")        return self.storage.get(food)    def put_food(self, username, food):        if username != 'admin':            raise Exception("This user is not allowed to put food")        self.storage.put(food)
复制代码
显然,代码有重复,作为一个有追求的工程师,我们严格遵守DRY(Don’t repeat yourself)原则,于是,代码被改写成了这样:
  1. def check_is_admin(username):    if username != 'admin':        raise Exception("This user is not allowed to get food")class Store(object):    def get_food(self, username, food):        check_is_admin(username)        return self.storage.get(food)    def put_food(self, username, food):        check_is_admin(username)        return self.storage.put(food)
复制代码
现在代码整洁一点了,但是,有装饰器能够做的更好:
  1. def check_is_admin(f):    def wrapper(*args, **kwargs):        if kwargs.get('username') != 'admin':            raise Exception("This user is not allowed to get food")        return f(*arg, **kargs)    return wrapperclass Storage(object):    @check_is_admin    def get_food(self, username, food):        return self.storage.get(food)    @check_is_admin    def put_food(self, username, food):        return storage.put(food)
复制代码
在这里,我们使用装饰器,就可以把参数检查和业务逻辑完全分离开来,让代码显得更加清晰。这也是比较Pythonic的代码。

5. 动态类型语言

我们再来看一个例子,该例子充分演示了动态类型语言与静态类型语言编程之间的差异。

在这个例子中,我们会收到很多不同的请求,对于不同的请求,调用不同的请求处理函数,这个需求如此常见,相信大家应该见过这样的代码:
  1. if (cmd == 'a')    processA()else if (cmd == 'b')    processB()else if (cmd == ‘c')    processC()else if (cmd == 'd')    processD()……else    raise NotImplementException
复制代码
在Python里面,我们可以先判断一个类,有没有这个函数,如果有,则获取这个函数,然后再调用。所以,我们的代码可以写成这样:
  1. class A:    def fetch_func(self, action_name):        func= getattr(self, action_name, None)        return func    def execute(self, action, msg):        func= self.fetch_func(action)        if func is None:            return False, "Action not found"        return func(action, msg)
复制代码
结论:所谓的Pythonic,其实并没有大家想的那么神秘,最终目的都是写出简洁优美的代码。写出简洁优美代码的思想在各个语言中都是一样的。如果你用其他编程语言写不出简洁优美的代码,那么,你也没办法用Python写出简介优美的代码。如果你能用其他语言写出很好的代码,那么,还是需要了解Python这门语言特有的一些语法和语言特性,充分利用Python里面比较好语言特性。这样,就能够写出Pythonic的代码了。
4#
热心的小回应  16级独孤 | 2021-1-9 06:04:24 发帖IP地址来自
《计算机程序的构造和解释》的作者哈尔·阿伯尔森曾这样说:
Programs must be written for people to read, and only incidentally for machines to execute.
好的代码具有可读性,Python之禅有一句话是:
Readability counts.(我也不知道怎么翻译才优雅,自己意会吧)
所谓Pythonic就是很具有Python风格的代码,是的,Python有自己独特的语言风格,很多时候,特别是有其它编程经验的Python初学者还是按照固有的思维习惯来写,比如:
变量交换
  1. >>> a = 1>>> b = 2>>> tmp = a>>> a = b>>> b = tmp
复制代码
pythonic
  1. a, b = b, a
复制代码
字符串链接
  1. names = ['raymond', 'rachel', 'matthew', 'roger',         'betty', 'melissa', 'judith', 'charlie']s = names[0]for name in names[1:]:    s += ', ' + nameprint(s)
复制代码
pythonic
  1. print(', '.join(names))
复制代码
链式比较操作
[code]age = 18if age > 18 and age
5#
热心的小回应  16级独孤 | 2021-1-9 06:04:25 发帖IP地址来自
简单说就是符合 Python 语言编程理念的代码风格。
具体的例子可以参考这个:
http://www.189works.com/article-41429-1.html
6#
热心的小回应  16级独孤 | 2021-1-9 06:04:26 发帖IP地址来自
引用自Code Style的一段话
Moreover, when a veteran Python developer (a Pythonista) points to portions of code and says they are not “Pythonic”, it usually means that these lines of code do not follow the common guidelines and fail to express the intent in what is considered the best (hear: most readable) way
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:3118703
帖子:623848
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP