python怎么将if和try一起用_Python使用try/catch还if效率更高一些?
“请求原谅”和“三思而后行”(有时也称为“请求许可”)是编写代码的两种相反的方法。如果你“三思而后行”,你首先要检查一切是否设置正确,然后再执行一个操作。例如,您要从文件中读取文本。那会出什么问题呢?好吧,文件可能不在您期望的位置。因此,首先检查文件是否存在:
import os
if os.path.exists("path/to/file.txt"):
...
# Or from Python 3.4
from pathlib import Path
if Path("/path/to/file").exists():
...
即使文件存在,也许你没有打开它的权限?所以让我们看看你是否能读到:
import os
if os.access("path/to/file.txt", os.R_OK):
...
但是如果文件损坏了怎么办?或者你没有足够的内存去读它?这个名单可以继续下去。最后,当你认为你检查了每一个可能的问题,你可以打开并阅读它:
with open("path/to/file.txt") as input_file:
return input_file.read()
根据您要执行的操作,可能需要执行很多检查。即使你认为你已经涵盖了所有内容,也不能保证某些意外的问题不会阻止你阅读此文件。所以,你可以“请求原谅”,而不是做所有的检查
有了“请求原谅”,你什么都不检查。您可以执行您想要的任何操作,但将其包装在try/catch块中。如果发生异常,则处理它。您不必考虑所有可能出错的地方,您的代码要简单得多(没有更多嵌套的ifs),而且这样通常会捕获更多的错误。这就是为什么Python社区通常更喜欢这种方法,通常称为“EAFP”——“请求原谅比请求许可更容易。”
下面是一个使用“请求原谅”方法读取文件的简单示例:
try:
with open("path/to/file.txt", "r") as input_file:
return input_file.read()
except IOError:
# Handle the error or just ignore it
这里我们正在捕捉IOError。如果您不确定可以引发哪种类型的异常,可以使用BaseException类捕捉所有异常,但一般来说,这是一种不好的做法。它将捕捉所有可能的异常(例如,当你想停止进程时,包括KeyboardInterrupt),所以尽量更具体一些。
“请求原谅”更干净。但是哪一个更快?
“请求原谅”与“三思而后行”-速度
是时候做个简单的测试了。假设我有一个类,我想从这个类中读取一个属性。但是我使用的是继承,所以我不确定是否定义了属性。我需要保护自己,要么检查它是否存在(“三思而后行”),要么抓住AttributeError(“请求原谅”):
# permission_vs_forgiveness.py
class BaseClass:
hello = "world"
class Foo(BaseClass):
pass
FOO = Foo()
# Look before you leap
def test_lbyl():
if hasattr(FOO, "hello"):
FOO.hello
# Ask for forgiveness
def test_aff():
try:
FOO.hello
except AttributeError:
pass
我们来测量这两个函数的速度。
$ python -m timeit -s "from permission_vs_forgiveness import test_lbyl" "test_lbyl()"
2000000 loops, best of 5: 155 nsec per loop
$ python -m timeit -s "from permission_vs_forgiveness import test_aff" "test_aff()"
2000000 loops, best of 5: 118 nsec per loop
你先看一下,再慢一点。
如果我们增加检查数量会怎么样?假设这次我们要检查三个属性,而不仅仅是一个:
# permission_vs_forgiveness.py
class BaseClass:
hello = "world"
bar = "world"
baz = "world"
class Foo(BaseClass):
pass
FOO = Foo()
# Look before you leap
def test_lbyl2():
if hasattr(FOO, "hello") and hasattr(FOO, "bar") and hasattr(FOO, "baz"):
FOO.hello
FOO.bar
FOO.baz
# Ask for forgiveness
def test_aff2():
try:
FOO.hello
FOO.bar
FOO.baz
except AttributeError:
pass
$ python -m timeit -s "from permission_vs_forgiveness import test_lbyl2" "test_lbyl2()"
500000 loops, best of 5: 326 nsec per loop
$ python -m timeit -s "from permission_vs_forgiveness import test_aff2" "test_aff2()"
2000000 loops, best of 5: 176 nsec per loop
“三思而后行”现在大约慢了85%(326/176≈1.852)。所以“请求原谅”不仅更容易阅读,而且在很多情况下,速度也更快。是的,你读得对,“在很多情况下,”不是“在所有情况下”!”
“EAFP”和“LBYL”的主要区别
如果属性实际上没有定义,会发生什么?看看这个例子:
# permission_vs_forgiveness.py
class BaseClass:
pass # "hello" attribute is now removed
class Foo(BaseClass):
pass
FOO = Foo()
# Look before you leap
def test_lbyl3():
if hasattr(FOO, "hello"):
FOO.hello
# Ask for forgiveness
def test_aff3():
try:
FOO.hello
except AttributeError:
pass
$ python -m timeit -s "from permission_vs_forgiveness import test_lbyl3" "test_lbyl3()"
2000000 loops, best of 5: 135 nsec per loop
$ python -m timeit -s "from permission_vs_forgiveness import test_aff3" "test_aff3()"
500000 loops, best of 5: 562 nsec per loop
形势已经好转。“请求原谅”现在是“三思而后行”的四倍多(562/135≈4.163)。这是因为这一次,我们的代码抛出了一个异常。而且处理异常的成本很高。
如果您希望您的代码经常失败,那么“三思而后行”可能会快得多。
决断
“请求原谅”的结果是代码更简洁,更容易发现错误,而且在大多数情况下,速度更快。难怪EAFP(“请求原谅比请求许可更容易”)在Python中是如此普遍的模式。即使在本文开头的示例中(检查文件是否存在os.path.exists)-如果您查看exists方法的源代码,就会发现它只是使用try/except。“三思而后行”通常会导致代码较长,可读性较差(使用嵌套的if语句)且速度较慢。按照这种模式,你有时可能会漏掉一两个判断。
请记住,处理异常是缓慢的。扪心自问:“这段代码是否会抛出异常更常见?如果答案是“是”,你可以用一个好的“IF”来解决这些问题,太好了!但在很多情况下,你无法预测你会遇到什么问题。使用“请求原谅”是非常好的-在你开始加速之前,你的代码应该是“正确的”。
python怎么将if和try一起用_Python使用try/catch还if效率更高一些?相关推荐
- python3 循环写入一对多键值对_为什么Python 3.6以后字典有序并且效率更高?
在Python 3.5(含)以前,字典是不能保证顺序的,键值对A先插入字典,键值对B后插入字典,但是当你打印字典的Keys列表时,你会发现B可能在A的前面. 但是从Python 3.6开始,字典是变成 ...
- python3.6字典有序_为什么从Python 3.6开始字典有序并效率更高
在Python 3.5(含)以前,字典是不能保证顺序的,键值对A先插入字典,键值对B后插入字典,但是当你打印字典的Keys列表时,你会发现B可能在A的前面. 但是从Python 3.6开始,字典是变成 ...
- python3.6字典有序_为什么Python 3.6以后字典有序并且效率更高?
在Python 3.5(含)以前,字典是不能保证顺序的,键值对A先插入字典,键值对B后插入字典,但是当你打印字典的Keys列表时,你会发现B可能在A的前面. 但是从Python 3.6开始,字典是变成 ...
- python排版word文档 效率_「word技巧」懂得这几个word排版小技巧,还怕效率不高?...
熟能生巧.作为一名职场人,使用word是不可避免的.Word玩得遛,工作效率就提高了.不过想要把word玩得遛,掌握一些技巧必不可少. 今天就来看看word排版上经常要用到的几个小技巧. 一.好用的F ...
- python安装matplotlib需要c编译_在Python 3.9上安装matplotlib提示需要FreeType更高版本的解决...
在Python 3.9(在Deepin系统中采用源码安装Python 3.9版本的方法)上安装matplotlib提示需要FreeType 2.3或更高版本,可以将MPLLOCALFREETYPE环境 ...
- python中123+5.0的执行结果_python实战笔记(一)
[Python注释] [Python变量] [Python运算符] [Python输入输出] * [输入函数] * [输出函数(3.x)] * [格式化输出] [分支] [循环] ### ...
- python的特性注定了代码无法保密_python 基础
谈谈你对python和其他语言的区别 python 中,变量是以内容为基准而不是像 c 中以变量名为基准: python 中,一个变量可以以多个名称访问: python 中,数字类型的值是不可变的: ...
- python 协程可以嵌套协程吗_Python实战异步爬虫(协程)+分布式爬虫(多进程)
引言:我们在写爬虫时常会遇到这样的问题,当需要爬取多个URL时,写一个普通的基于requests库的爬虫程序爬取时间会很长.因为是顺序请求网页的,而网页请求和获得响应过程比较耗费时间,程序不得不等待获 ...
- python矩阵拼接_numpy数组拼接简单示例_python
这篇文章主要介绍了numpy数组拼接简单示例,涉及对numpy数组的介绍,numpy数组的属性等内容,具有一定借鉴价值,需要的朋友可以参考下. NumPy数组是一个多维数组对象,称为ndarray.其 ...
最新文章
- dedecms织梦专题节点列表内容怎么实现分页
- list index out of range怎么解决_“卿卿我我”和“如胶似漆”英语怎么说?
- hdu 5072 Coprime
- 与年轻人的“要疯”五年,安踏如何保持新鲜感与吸引力?
- java的继承_java中的继承(一)
- 如果测试你的MongoDB应用升级?
- python3.8学习_python3.8.1 入门基础学习 之 【字典】 学习
- 到无限(溪流)和超越!
- QML笔记-整合C++及单例模式管理QML中控件
- I2C 协议分析和学习
- 4KB/2MB PAE分页模式下的线性地址翻译以及CR3
- 看电影的计算机配置,专门看电影的电脑主机需要什么配置?
- 轻量容器和注射依赖 的自实现
- JQuery each详细用法
- MIPI D-PHY IP 使用说明(二)
- c++避坑指南-除数为0
- linux蓝牙打印机驱动安装失败怎么办,打印机驱动安装失败怎么办?
- mysql数据库的主从同步(主服务器存在内网IP)
- Pycharm使用远程服务器解释器
- Flowable Exclusive gateway has no outgoing sequence flow
热门文章
- Hadoop之Yarn工作机制详解
- 大剑无锋之Redis面试题【推荐】
- Error: Could not open client transport with JDBC Uri: jdbc:hive2://henu2:10000: java.n et.ConnectExc
- 爬虫 spider05——使用httpclient发送get请求、post请求
- map反转key value
- 数据分析-pands分析美国选民对总统的喜好(python实现)
- gradle的多项目构建(九)
- 蓝桥杯 ADV-202 算法提高 最长公共子序列
- 大话主题敏感PageRank
- jQuery事件3——trigger触发事件