pythonic之路(二)
来源:互联网 发布:淘宝上怎么购买呼死你 编辑:程序博客网 时间:2024/04/25 13:28
pythonic之路—-编写简洁清晰python代码(二)
十、多用生成器和生成器表达式
至于什么是生成器,可参看我的另一篇文章迭代对象、迭代器、生成器浅析。
如果需要迭代处理的序列包含了无限的元素,比如串口读回来的数据流、某网站发帖信息流等,生成器是最好选择,否则用list类容器的话数据会占用完内存,除非不断地把旧值pop掉,但这样做显然没有生成器那么简洁清晰。
如果需要从一个很大的序列每次提取一个值来做非常复杂的运算,那么用list类容器一次性把数据全读入内存显然会降低运算效率,这时最好用生成器。
故,生成器是你python路上的挚友。
一个例子,获取Twitter上某个关键字对应的数据流。
list实现:
def get_twitter_stream_for_keyword(keyword): """Get's the 'live stream', but only at the moment the function is initially called. To get more entries, the client code needs to keep calling 'get_twitter_livestream_for_user'. Not ideal. """ imaginary_twitter_api = ImaginaryTwitterAPI() if imaginary_twitter_api.can_get_stream_data(keyword): return imaginary_twitter_api.get_stream(keyword) current_stream = get_twitter_stream_for_keyword('#jeffknupp') for tweet in current_stream: process_tweet(tweet)# Uh, I want to keep showing tweets until the program is quit.# What do I do now? Just keep calling# get_twitter_stream_for_keyword? That seems stupid.def get_list_of_incredibly_complex_calculation_results(data): return [first_incredibly_long_calculation(data), second_incredibly_long_calculation(data), third_incredibly_long_calculation(data), ]
generator实现:
def get_twitter_stream_for_keyword(keyword): """Now, 'get_twitter_stream_for_keyword' is a generator and will continue to generate Iterable pieces of data one at a time until 'can_get_stream_data(user)' is False (which may be never). """ imaginary_twitter_api = ImaginaryTwitterAPI() while imaginary_twitter_api.can_get_stream_data(keyword): yield imaginary_twitter_api.get_stream(keyword) # Because it's a generator, I can sit in this loop until # the client wants to break out for tweet in get_twitter_stream_for_keyword('#jeffknupp'): if got_stop_signal: break process_tweet(tweet)def get_list_of_incredibly_complex_calculation_results(data): """A simple example to be sure, but now when the client code iterates over the call to 'get_list_of_incredibly_complex_calculation_results', we only do as much work as necessary to generate the current item. """ yield first_incredibly_long_calculation(data) yield second_incredibly_long_calculation(data) yield third_incredibly_long_calculation(data)
十一、多用上下文管理器with
对于文件的操作上下文管理器可谓是将遇良才,极其适用。
上下文管理器本质上是一个实现了__enter__()
和__exit__()
魔法方法的类。除了python内置的上下文管理器,自己也可以实现一个,只要加入这两个魔法方法即可。也可以用@contextmanager
装饰器来实现上下文管理器。
一个官方例子。当执行到yield
子句时,with
下面的代码将被执行,类似于open
文件时的f.read()
。其实open
返回的就是一个生成器,源码内部有yield
语句。
from contextlib import contextmanager@contextmanagerdef tag(name): print("<%s>" % name) yield print("</%s>" % name)with tag("h1"): print("foo")#输出<h1> foo </h1>
十二、用单下划线_
作为占位符忽略掉不使用的数据
有时候某些数据的出现是毫无用途的,这时候就不要把它赋值给某个变量了,而是直接舍弃掉,也可以节约点内存。
s = "afmldskmfl"occurrences = {}for _,e in enumerate(s): occurrences1[e]=occurrences1.get(e,0)+1#返回{';': 1, 'a': 3, 'd': 1, 'f': 1, 'k': 1, 'l': 1, 's': 3}
(name, age, _, _) = get_user_info(user)
十三、直接交换两个变量的值,不要引入临时变量作为过渡
a, b = 1, 2a, b = b, a+b#返回a = 2, b = 3
十四、使用全大写字母表示全局变量或常数。
LIGHT_SPEED = 299792458#[M/S]
十五、在每个程序中都加入 if __name__ == __main__
语句
在每一个.py
文件末尾最好都加入if __name__ == __main__: do_something
。尤其是当该文件作为模块导入时更方便。
可将调试语句和零时验证程序正确与否的语句放在if条件句后面,很方便简单调试及结果显示,如果一旦作为模块导入了,那么if条件句后面的代码块都会被忽略,因为此时的__name__
不再是__main__
了。
十六、用sys.exit
返回程序错误代码
对于任何程序,最好都定义一个返回值为0的main()
函数。在main()
内部通过调用sys.exit
返回错误信息,在if __name__ == __main__
里通过sys.exit(main())
调用main()
,如果正常运行则返回0并安全退出。
这样的写法可直接用于Unix pipelines和SHELL。
import sysdef do_stuff(argument): passdef do_stuff_with_result(result): passdef main(): if len(sys.argv) < 2: sys.exit('You forgot to pass an argument') argument = sys.argv[1] result = do_stuff(argument) if not result: sys.exit(1) do_stuff_with_result(result) return 0if __name__ == '__main__': sys.exit(main())
十七、永远不要使用from package import *
来导入包或模块
*
是个通配符,会将package里的所有东西都导入进来,如果package里有个模块名字为foo
,而自己写的程序里也有一个子程序叫foo
,这会导致命名空间冲突,因为from package import *
污染了当前命名空间。
十八、导入模块顺序
其实,可以以任意顺序导入模块,但最好用约定俗成的顺序。
- standard library modules
- third-party library modules installed in site-packages
- modules local to the current project
如果每一类型模块包含了好几个模块,最好用字母顺序排序。
十九、善用自带电池,不要重新造轮子
python是一门自带电池的语言,扩展库和模块非常丰富。每当遇到一个功能,首先考虑标准库有没有实现,其次再想办法自己造轮子。
充分利用标准库好处良多,最主要的有两点,第一,节省程序开发时间,同时标准库模块的性能更高;第二、代码更加清晰简洁,让维护者更轻松。
如果标准库里没有找到你需要的功能,那就上PyPI (the Python Package Index)找找,PyPI维护着超过27000个各种包。如果PyPI里也没有,那就上GitHub找;还没有的话那就自己造,如果能造出很好的轮子,可以申请添加到PyPI,让整个python社区受益。
如果找到了一个包,最好用python包管理器pip进行安装,语法为pip install <package name>
。也可以上GitHub下载源码,在CMD里通过python install setup.py
手动安装,但是这种方法不方便,因为有些包还需要别的包来支持,所以还得手动安装支持包(如果支持包之前没安装过)。但用pip就很方便了,会自动检测支持包并自动安装。
二十、用os.path
模块操作文件路径
os.path
包含了处理文件路径的所有功能,不要用“+”去操作路径。
一个重命名文件的例子。
from datetime import dateimport oscurrent_directory = os.getcwd()filename_to_archive = 'test.txt'new_filename = os.path.splitext(filename_to_archive)[0] + '.bak'target_directory = os.path.join(current_directory, 'archives')today = date.today()new_path = os.path.join(target_directory, str(today))if (os.path.isdir(target_directory)): if not os.path.exists(new_path): os.mkdir(new_path) os.rename( os.path.join(current_directory, filename_to_archive), os.path.join(new_path, new_filename))
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(内容同步更新到微信公众号python数学物理,微信号python_math_physics)
- pythonic之路(二)
- pythonic之路(一)
- Python函数式编程---- Pythonic 之路
- python编码之pythonic
- Pythonic (二 yield上, Generator)
- pythonic
- Pythonic
- Pythonic
- pythonic
- 构造Pythonic C module(续1)
- python学习笔记(一 pythonic)
- Be-Pythonic
- pythonic examples
- pythonic dict
- python-pythonic
- 什么是Pythonic?
- pythonic 1
- Pythonic QuickSort
- Java ActiveMQ简介以及springboot集成activeMQ实现消息队列监听以及实现MQ延迟
- java常见代码面试题
- XShell实现Windows主机与Linux云服务器之间的文件传输
- SSH2整合:'hibernate.dialect' not set 解决方案
- HDU
- pythonic之路(二)
- idea中刷新页面无反应
- 找出不是两个数组共有的元素
- Metasploit 攻击
- 无界面 socket通信模拟在线评测
- 解决Error:Could not determine the class-path for interface com.android.builder.model.AndroidProject.
- MyBatis DAO层有多个参数的处理
- consul UI用127可以访问,指定ip无法访问
- 微信网页授权,获取微信code,获取access_tocken,获取用户信息