Python中的EAFP原理是啥?

Posted

技术标签:

【中文标题】Python中的EAFP原理是啥?【英文标题】:What is the EAFP principle in Python?Python中的EAFP原理是什么? 【发布时间】:2012-07-06 19:59:44 【问题描述】:

在 Python 中“使用 EAFP 原则”是什么意思?你能提供任何例子吗?

【问题讨论】:

不符合 Guido:mail.python.org/pipermail/python-dev/2014-March/133118.html 【参考方案1】:

来自glossary:

请求宽恕比请求许可更容易。这种常见的 Python 编码风格假设存在有效的键或属性,如果假设被证明是错误的,则捕获异常。这种简洁快速的风格的特点是存在许多tryexcept 语句。该技术与许多其他语言(如 C)常见的LBYL style 形成对比。

一个例子是尝试访问字典键。

EAFP:

try:
    x = my_dict["key"]
except KeyError:
    # handle missing key

LBYL:

if "key" in my_dict:
    x = my_dict["key"]
else:
    # handle missing key

LBYL 版本必须在字典中搜索两次键,并且可能也被认为可读性稍差。

【讨论】:

一个改进是另一个优点是避免竞争条件......例如,只需尝试打开一个文件,如果你得到它,你就会得到它。而不是看到如果你能得到它,然后试图得到它并意识到在检查和访问尝试之间的极短时间里,你可以更长的时间得到它。 Python 还提供了一种避免这两种情况的方法,如果处理程序只是在密钥不存在时为 x 分配默认值:x = mydict.get('key') 将返回 None 如果'key' 不在my_dict 中;你也可以做.get('key', <something>),然后如果键不在字典中,x 将被分配一些东西。 dict.setdefault()collections.defaultdict 也是避免过多代码的好东西。 我认为except KeyErrorAttributeError 很简单,但也有一些最糟糕的例子。很多次我因为except AttributeError 被放置在错误的位置而被困在调试某些东西上,这最终导致了在链中更深层次的错误属性错误。我认为更好的例子是:try: open() ... except: IOError。或try: parseLine() ... except ParseError @ski 这是一个稍微不同的问题。您应该始终尽量减少 try 块,以避免捕获错误的异常。另请注意,我通常不喜欢 EAFP 样式。我只是在这里回答这个问题,并说明有些人更喜欢它。我会根据具体情况决定哪种代码对我来说最易读。 我认为值得一提的是,Grace Hopper 可能是这句话的来源,她引用了她的话:“敢于行动。请求宽恕比获得许可更容易”(不限于编程)。【参考方案2】:

我将尝试用另一个例子来解释它。

这里我们尝试访问文件并在控制台中打印内容。

LBYL - 三思而后行:

我们可能想检查我们是否可以访问该文件,如果可以,我们将打开它并打印内容。如果我们无法访问该文件,我们将点击else 部分。这是一个竞争条件的原因是因为我们首先进行了访问检查。当我们到达with open(my_file) as f: 时,可能由于某些权限问题(例如另一个进程获得了独占文件锁),我们无法再访问它。这段代码可能会抛出一个错误,我们将无法捕捉到该错误,因为我们认为我们可以访问该文件。

import os

my_file = "/path/to/my/file.txt"

# Race condition
if os.access(my_file, os.R_OK):
    with open(my_file) as f:
        print(f.read())
else:
    print("File can't be accessed")

EAFP - 请求宽恕比请求许可更容易:

在这个例子中,我们只是试图打开文件,如果我们不能打开它,它会抛出一个IOError。如果可以,我们将打开文件并打印内容。因此,我们不是要求,而是尝试去做。如果它有效,那就太好了!如果没有,我们会捕获错误并进行处理。

# # No race condition
try:
    f = open(my_file)
except IOError as e:
    print("File can't be accessed")
else:
    with f:
        print(f.read())

【讨论】:

我不确定将其描述为竞争条件是否正确。该文件是否可访问。 @ds4940 如果文件可访问性在第 6 行和第 7 行之间发生变化,即在检查文件是否可访问和打开文件之间发生变化,这是竞争条件。 @MarkusvonBroady 同意,编辑答案以提供比赛条件中其他参与者的示例。 我一直认为 LBYL 是首选的做事方式,而不是 try, except 块,对吗? @SurpriseDog 可能是其他语言,但不是 Python。 Python 期望您使用异常,因此它已被优化为在不引发异常时高效。异常提高了可读性,因为错误处理代码在工作代码之后组合在一起,并且在需要在线处理每个可能的错误时减少了缩进量。【参考方案3】:

我称之为“乐观编程”。这个想法是大多数时候人们会做正确的事情,错误应该很少。因此,首先编写代码以使“正确的事情”发生,然后在错误发生时捕获错误。

我的感觉是,如果用户要犯错误,他们应该是承担时间后果的人。以正确方式使用该工具的人会被快速通过。

【讨论】:

或“try-catch”而不是“if-else” 我的意思是寻找可能的已知错误,例如电话号码字段中的邮政编码。错误应该被正确处理,而不是通过 catch 例程。

以上是关于Python中的EAFP原理是啥?的主要内容,如果未能解决你的问题,请参考以下文章

python Python EAFP与LBYL的速度

为什么在Python中“更容易请求宽恕而不是获得权限”?

哈士奇的工作原理是啥?

“站点包”中的“站点”实际上是啥意思?

java 中的修饰符transient是啥意识他的原理是啥?

快照测试的工作原理以及 toMatchSnapshot() 函数在 React 组件的 Jest 快照测试中的作用是啥?