你可能会想到这种,但这本质上与上面并无区别:[wangbm@localhost ~]$ python -c \"print('\n'.join(__import__('sys').path))\"/usr/lib/python2.7/site-packages/pip-18.1-py2.7.egg/usr/lib/python2.7/site-packages/redis-3.0.1-py2.7.egg/usr/lib64/python27.zip/usr/lib64/python2.7/usr/lib64/python2.7/plat-linux2/usr/lib64/python2.7/lib-tk/usr/lib64/python2.7/lib-old/usr/lib64/python2.7/lib-dynload/home/wangbm/.local/lib/python2.7/site-packages/usr/lib64/python2.7/site-packages/usr/lib64/python2.7/site-packages/gtk-2.0/usr/lib/python2.7/site-packages这里我要介绍的是比上面两种都方便得多的方法,一行命令即可解决。[wangbm@localhost ~]$ python3 -m sitesys.path = ['/home/wangbm','/usr/local/Python3.7/lib/python37.zip','/usr/local/Python3.7/lib/python3.7','/usr/local/Python3.7/lib/python3.7/lib-dynload','/home/wangbm/.local/lib/python3.7/site-packages','/usr/local/Python3.7/lib/python3.7/site-packages',]USER_BASE: '/home/wangbm/.local' (exists)USER_SITE: '/home/wangbm/.local/lib/python3.7/site-packages' (exists)ENABLE_USER_SITE: True从输出你可以发现,这个列的路径会比 sys.path 更全,它包含了用户环境的目录。将嵌套 for 循环写成单行我们经常会如下这种嵌套的 for 循环代码:list1 = range(1,3)list2 = range(4,6)list3 = range(7,9)for item1 in list1:for item2 in list2:for item3 in list3:print(item1+item2+item3)这里仅仅是三个 for 循环,在实际编码中,有可能会有更层。这样的代码,可读性非常的差,很多人不想这么写,可又没有更好的写法。这里介绍一种我常用的写法,使用 itertools 这个库来实现更优雅易读的代码。from itertools import productlist1 = range(1,3)list2 = range(4,6)list3 = range(7,9)for item1,item2,item3 in product(list1, list2, list3):print(item1+item2+item3)输出如下:$ python demo.py1213131413141415如何使用 print 输出日志初学者喜欢使用 print 来调试代码,并记录程序运行过程。但是 print 只会将内容输出到终端上,不能持久化到日志文件中,并不利于问题的排查。如果你热衷于使用 print 来调试代码(虽然这并不是最佳做法),记录程序运行过程,那么下面介绍的这个 print 用法,可能会对你有用。Python 3 中的 print 作为一个函数,由于可以接收更多的参数,所以功能变为更加强大,指定一些参数可以将 print 的内容输出到日志文件中。代码如下:>>> with open('test.log', mode='w') as f:... print('hello, python', file=f, flush=True)>>> exit$ cat test.loghello, python如何快速计算函数运行时间计算一个函数的运行时间,你可能会这样子做:import timestart = time.time# run the functionend = time.timeprint(end-start)你看看你为了计算函数运行时间,写了几行代码了。有没有一种方法可以更方便的计算这个运行时间呢?有。有一个内置模块叫 timeit,使用它,只用一行代码即可:import timeimport timeitdef run_sleep(second):print(second)time.sleep(second)# 只用这一行print(timeit.timeit(lambda :run_sleep(2), number=5))运行结果如下:2222210.020059824利用自带的缓存机制提高效率缓存是一种将定量数据加以保存,以备迎合后续获取需求的处理方式,旨在加快数据获取的速度。数据的生成过程可能需要经过计算,规整,远程获取等操作,如果是同一份数据需要多次使用,每次都重新生成会大大浪费时间。所以,如果将计算或者远程请求等操作获得的数据缓存下来,会加快后续的数据获取需求。为了实现这个需求,Python 3.2 + 中给我们提供了一个机制,可以很方便的实现,而不需要你去写这样的逻辑代码。这个机制实现于 functool 模块中的 lru_cache 装饰器。@functools.lru_cache(maxsize=None, typed=False)参数解读:maxsize:最多可以缓存多少个此函数的调用结果,如果为None,则无限制,设置为 2 的幂时,性能最佳;typed:若为 True,则不同参数类型的调用将分别缓存。举个例子:from functools import lru_cache@lru_cache(None)def add(x, y):print(\"calculating: %s + %s\" % (x, y))return x + yprint(add(1, 2))print(add(1, 2))print(add(2, 3))输出如下,可以看到第二次调用并没有真正的执行函数体,而是直接返回缓存里的结果:calculating: 1 + 233calculating: 2 + 35下面这个是经典的斐波那契数列,当你指定的 n 较大时,会存在大量的重复计算:def fib(n):if n < 2:return nreturn fib(n - 2) + fib(n - 1)第六点介绍的 timeit,现在可以用它来测试一下到底可以提高多少的效率。不使用 lru_cache 的情况下,运行时间 31 秒。import timeitdef fib(n):if n < 2:return nreturn fib(n - 2) + fib(n - 1)print(timeit.timeit(lambda :fib(40), number=1))# output: 31.2725698948由于使用了 lru_cache 后,运行速度实在太快了,所以我将 n 值由 30 调到 500,可即使是这样,运行时间也才 0.0004 秒。提高速度非常显著。import timeitfrom functools import lru_cache@lru_cache(None)def fib(n):if n < 2:return nreturn fib(n - 2) + fib(n - 1)print(timeit.timeit(lambda :fib(500), number=1))# output: 0.0004921059880871326在程序退出前执行代码的技巧使用 atexit 这个内置模块,可以很方便的注册退出函数。不管你在哪个地方导致程序崩溃,都会执行那些你注册过的函数。示例如下:如果clean函数有参数,那么你可以不用装饰器,而是直接调用atexit.register(clean_1, 参数1, 参数2, 参数3='xxx')。可能你有其他方法可以处理这种需求,但肯定比上不使用 atexit 来得优雅,来得方便,并且它很容易扩展。但是使用atexit 仍然有一些局限性,比如:如果程序是被你没有处理过的系统信号杀死的,那么注册的函数无法正常执行。如果发生了严重的 Python 内部错误,你注册的函数无法正常执行。如果你手动调用了os._exit,你注册的函数无法正常执行。实现类似 defer 的延迟调用在 Golang 中有一种延迟调用的机制,关键字是 defer,例如下面的示例:import \"fmt\"func myfunc {fmt.Println(\"B\")}func main {defer myfuncfmt.Println(\"A\")}输出如下,myfunc 的调用会在函数返回前一步完成,即使你将 myfunc 的调用写在函数的第一行,这就是延迟调用。AB那么在 Python 中否有这种机制呢?当然也有,只不过并没有 Golang 这种简便。在 Python 可以使用上下文管理器达到这种效果:import contextlibdef callback:print('B')with contextlib.ExitStack as stack:stack.callback(callback)print('A')输出如下:AB如何流式读取数G超大文件使用 with...open... 可以从一个文件中读取数据,这是所有 Python 开发者都非常熟悉的操作。但是如果你使用不当,也会带来很大的麻烦。比如当你使用了 read 函数,其实 Python 会将文件的内容一次性的全部载入内存中,如果文件有 10 个G甚至更多,那么你的电脑就要消耗的内存非常巨大。# 一次性读取with open(\"big_file.txt\", \"r\") as fp:content = fp.read对于这个问题,你也许会想到使用 readline 去做一个生成器来逐行返回。def read_from_file(filename):with open(filename, \"r\") as fp:yield fp.readline可如果这个文件内容就一行呢,一行就 10个G,其实你还是会一次性读取全部内容。最优雅的解决方法是,在使用 read 方法时,指定每次只读取固定大小的内容,比如下面的代码中,每次只读取 8kb 返回。def read_from_file(filename, block_size = 1024 8):with open(filename, \"r\") as fp:while True:chunk = fp.read(block_size)if not chunk:breakyield chunk上面的代码,功能上已经没有问题了,但是代码看起来代码还是有些臃肿。借助偏函数和 iter 函数可以优化一下代码:from functools import partialdef read_from_file(filename, block_size = 1024 8):with open(filename, \"r\") as fp:for chunk in iter(partial(fp.read, block_size), \"\"):yield chunk☞架构的腐化是必然的。
☞腾讯云 AI 在新基建领域下一盘什么大棋☞张一鸣是如何练就字节跳动的☞性能超越最新序列推荐模型,华为诺亚方舟提出记忆增强的图神经网络☞DevOps 在移动应用程序开发中扮演什么角色?☞稳定币经济:十大稳定币简史
(图片来源网络,侵删)
0 评论