首页 » 网站建设 » phpoutputexc技巧_5年 Python 功力总结了 10 个开拓技巧

phpoutputexc技巧_5年 Python 功力总结了 10 个开拓技巧

访客 2024-12-13 0

扫一扫用手机浏览

文章目录 [+]

来源 | Python编程光阴

如何在运行状态查看源代码

phpoutputexc技巧_5年 Python 功力总结了 10 个开拓技巧

查看函数的源代码,我们常日会利用 IDE 来完成。

phpoutputexc技巧_5年 Python 功力总结了 10 个开拓技巧
(图片来自网络侵删)

比如在 PyCharm 中,你可以 Ctrl +鼠标点击进入函数的源代码。

那如果没有 IDE 呢?

当我们想利用一个函数时,如何知道这个函数须要吸收哪些参数呢?

当我们在利用函数时涌现问题的时候,如何通过阅读源代码来排查问题所在呢?

这时候,我们可以利用 inspect 来代替 IDE 帮助你完成这些事:

# demo.pyimport inspectdef add(x, y):return x + yprint(\"大众===================\"大众)print(inspect.getsource(add))

运行结果如下:

$ python demo.py===================def add(x, y):return x + y

如何关闭非常自动关联高下文

当你在处理非常时,由于处理不当或者其他问题,再次抛出另一个非常时,往外抛出的非常也会携带原始的非常信息。

就像这样子:

try:print(1 / 0)except Exception as exc:raise RuntimeError(\"大众Something bad happened\"大众)

从输出可以看到两个非常信息:

Traceback (most recent call last):File \"大众demo.py\"大众, line 2, in <module>print(1 / 0)ZeroDivisionError: division by zeroDuring handling of the above exception, another exception occurred:Traceback (most recent call last):File \"大众demo.py\公众, line 4, in <module>raise RuntimeError(\"大众Something bad happened\公众)RuntimeError: Something bad happened

如果在非常处理程序或 finally 块中引发非常,默认情形下,非常机制会隐式事情会将先前的非常附加为新非常的 __context__属性。
这便是 Python 默认开启的自动关联非常高下文。

如果你想自己掌握这个高下文,可以加个 from 关键字(from 语法会有个限定,便是第二个表达式必须是另一个非常类或实例。
)来表明你的新非常是直接由哪个非常引起的。

try:print(1 / 0)except Exception as exc:raise RuntimeError(\"大众Something bad happened\公众) from exc

输出如下:

Traceback (most recent call last):File \公众demo.py\公众, line 2, in <module>print(1 / 0)ZeroDivisionError: division by zeroThe above exception was the direct cause of the following exception:Traceback (most recent call last):File \"大众demo.py\公众, line 4, in <module>raise RuntimeError(\"大众Something bad happened\"大众) from excRuntimeError: Something bad happened

当然,你也可以通过 with_traceback 方法为非常设置高下文__context__属性,这也能在 traceback 更好的显示非常信息。

try:print(1 / 0)except Exception as exc:raise RuntimeError(\公众bad thing\"大众).with_traceback(exc)

末了,如果我想彻底关闭这个自动关联非常高下文的机制?有什么办法呢?

可以利用 raise...from None,从下面的例子上看,已经没有了原始非常。

$ cat demo.pytry:print(1 / 0)except Exception as exc:raise RuntimeError(\"大众Something bad happened\公众) from None$$ python demo.pyTraceback (most recent call last):File \"大众demo.py\公众, line 4, in <module>raise RuntimeError(\公众Something bad happened\"大众) from NoneRuntimeError: Something bad happened(PythonCodingTime)

最快查看包搜索路径的办法

当你利用 import 导入一个包或模块时,Python 会去一些目录下查找,而这些目录是有优先级顺序的,正凡人会利用 sys.path 查看。

>>> import sys>>> from pprint import pprint>>> pprint(sys.path)['','/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']>>>

那有没有更快的办法呢?

我这有一种连console 模式都不用进入的方法呢!

你可能会想到这种,但这实质上与上面并无差异:

[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 在移动运用程序开拓中扮演什么角色?

☞稳定币经济:十大稳定币简史

标签:

相关文章

phpmcryptblowfish技巧_简述Blowfish加密算法

Blowfish加密算法的特点:1. 对称加密,即加密的密钥和解密的密钥是相同的;2. 每次加密之后的结果是不同的(这也是老夫比较...

网站建设 2024-12-15 阅读0 评论0

学IT之路,探索数字时代的知识之旅

在数字化时代的浪潮中,信息技术(IT)已经渗透到社会生活的方方面面。对于有志于投身IT行业的人来说,学习IT之路既充满挑战,又充满...

网站建设 2024-12-15 阅读0 评论0

探索“its”的魅力,一词多义,沟通无界

在英语词汇中,“its”一词可谓独具魅力,它以简洁的三个字母,承载着丰富的语义和用法。从字面意义上看,“its”是指代某个事物或某...

网站建设 2024-12-15 阅读0 评论0

php存取文件技巧_PHP获取目录下文件

1、获取目录下文件,不包括子目录//获取某目录下所有文件、目录名(不包括子目录下文件、目录名) $handler = opendi...

网站建设 2024-12-15 阅读0 评论0