Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/322.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/reporting-services/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
这是为什么;请求原谅比获得许可更容易。”;用Python?_Python_Coding Style - Fatal编程技术网

这是为什么;请求原谅比获得许可更容易。”;用Python?

这是为什么;请求原谅比获得许可更容易。”;用Python?,python,coding-style,Python,Coding Style,为什么在Python中“请求原谅比获得许可更容易”()被认为是良好的实践?作为一名编程新手,我的印象是,与使用其他检查相比,使用除例程之外的许多try…会导致代码臃肿且可读性较差 EAFP方法的优势是什么 注:我知道这里也有类似的问题,但它们大多涉及一些具体的例子,而我更感兴趣的是原则背后的理念。,相反的方法与断言无关,它只是意味着在尝试访问可能不存在的内容之前添加一个检查 Python是EAFP的原因是,与其他语言(例如Java)不同,在Python中捕获异常是相对便宜的操作,这就是为什么鼓励

为什么在Python中“请求原谅比获得许可更容易”()被认为是良好的实践?作为一名编程新手,我的印象是,与使用其他检查相比,使用除例程之外的许多
try…会导致代码臃肿且可读性较差

EAFP方法的优势是什么

注:我知道这里也有类似的问题,但它们大多涉及一些具体的例子,而我更感兴趣的是原则背后的理念。

,相反的方法与断言无关,它只是意味着在尝试访问可能不存在的内容之前添加一个检查

Python是EAFP的原因是,与其他语言(例如Java)不同,在Python中捕获异常是相对便宜的操作,这就是为什么鼓励您使用它

EAFP示例:

try:
    snake = zoo['snake']
except KeyError as e:
    print "There's no snake in the zoo"
    snake = None
LBYL的示例:

if 'snake' in zoo:
    snake = zoo['snake']
else:
    snake = None

这里混合了两种东西:断言和基于EAFP的逻辑

断言用于验证函数的契约,即其前置和后置条件,有时还验证其不变量。它们确保函数按其应使用的方式使用。但是,它们不适用于代码流,因为它们完全会在出错时中断执行。一个常见的例子是检查函数调用中的
None
参数

在Python中,通常避免过多使用断言。通常,您应该期望代码的用户正确使用它。例如,如果您记录了一个函数,使其接受的参数不是
None
,则无需使用断言来验证该参数。相反,只要期望有一个值。如果由于“无”值而出现错误,那么无论如何它都会冒泡,因此用户知道他们做错了什么。但是你不应该总是检查所有的东西

现在,EAFP有所不同。它用在控制流中,或者更确切地说,它避免了额外的控制流,而希望事情是正确的,如果不正确,则捕获异常。显示差异的常见示例是字典中的密钥访问:

# LBYL
if key in dic:
    print(dic[key])
else:
    handleError()

# EAFP
try:
    print(dic[key])
except KeyError:
    handleError()
现在看起来非常相似,不过您应该记住,LBYL解决方案会检查字典两次。与捕获异常的所有代码一样,只有在键不存在的情况下才应该执行此操作。因此,如果通常情况下,提供的密钥被排除在字典中,那么它是EAFP,您应该直接访问它。如果您不希望该键出现在字典中,那么您可能应该首先检查它的存在性(虽然在Python中异常比较便宜,但它们仍然不是免费的,所以在异常情况下保留它们)


EAFP的一个好处是,在库或应用程序的逻辑深处,
键来自上面,您可以假定这里传递了一个有效的键。因此,您不需要在这里捕获异常,只需让它们冒泡到代码中的更高点,然后您就可以处理错误。这使您可以拥有完全不受此类检查的低级函数。

问得好!关于“原则背后的哲学”的问题很少

关于这个问题,我甚至想进一步说,它提到的“如果假设被证明是错误的,则缓存例外情况”在这方面有些误导。因为,让我们面对它,下面的第二个代码片段看起来并不是更“干净和快速”(在前面的定义中使用的术语)。难怪OP问了这个问题

#LBYL
如果输入dic:
打印(dic[键])
其他:
handleError()
#EAFP
尝试:
打印(dic[键])
除KeyError外:
handleError()
我想说,EAFP闪耀的真正时刻是,您不需要编写
尝试。。。除了…
之外,至少在大多数底层代码库中没有。因为。考虑到这一点,现在,让我们将第二段改写为:

#真正的EAFP
打印(dic[键])

现在,这不是真正的EAFP方法干净且快速吗?

我将从@raylou展开回答

LBYL的问题是,它实际上一般不起作用。除非您有单线程应用程序,否则始终存在可能的争用条件:

# LBYL
if key in dic:
    # RACE CONDITION
    print(dic[key])
else:
    handleError()

# EAFP
try:
    print(dic[key])
except KeyError:
    handleError()
可以在
if
检查和
print
之间向dict添加一个键。在这种情况下,这听起来不太可能。但是,如果您所做的检查是针对DB、API或任何可以与应用程序数据异步更改的外部数据源,则更有可能发生这种情况

这意味着实施LBYL的“正确”方式是:

if key in dic:
    try:
        print(dic[key])
    except KeyError:
        handleError()
else:
    handleError()
注意
try
/
except
子句与 EAFP方法

因为即使在使用LBYL方法时也必须处理异常EAFP样式,所以您最好首先使用EAFP方法

我使用
if
检查的唯一情况是,接下来的操作(
print
在本例中)启动起来是否非常昂贵/耗时。这将是罕见的,并且不是每次都使用
if
检查的理由


一句话:LBYL在一般情况下不起作用,但EAFP起作用。优秀的开发人员专注于通用的解决方案模式,他们可以自信地在广泛的问题上使用。学会始终如一地使用EAFP。

断言不适用于代码流。@IgnacioVazquez Abrams您能详细说明一下吗?据我所知,它们是<代码>尝试的替代品…除了<代码>?我应该改变这个问题吗?它们应该用来确保你的程序在梨形的情况下不会做任何愚蠢的事情,而不是检查是否有人传递了一个整数而不是字符串。好的-我删除了
assert
。显然,我没有告诉你