Python 嵌套尝试除了 vs if、elif、else
Python nested try except vs if, elif, else
我正在尝试熟悉 Python 的最佳实践。根据 Python 的禅宗,请求宽恕比请求许可更容易,但是,它也说平面优于嵌套和可读性。你会如何处理这个问题:
我有3本词典。我有一把钥匙,我想测试钥匙是否在字典中。钥匙只会在其中之一。根据它所在的字典,我想做不同的事情。
使用try/except,我得出以下解决方案:
try:
val = dict1[key]
except KeyError:
try:
val = dict2[key]
except KeyError:
try:
val = dict3[key]
except KeyError:
do_stuff_key_not_found()
else:
do_stuff_dict3()
else:
do_stuff_dict2()
else:
do_stuff_dict1()
根据 Python 的 EAFP 原则,这将是可行的方法,但它看起来很杂乱,而且可读性不是很好。
一个更简单的解决方案是:
if key in dict1:
val = dict1[key]
do_stuff_dict1()
elif key in dict2:
val = dict2[key]
do_stuff_dict2()
elif key in dict3:
val = dict3[key]
do_stuff_dict3()
else:
do_stuff_key_not_found()
处理这种情况更Pythonic的方法是什么?我应该坚持 EAFP 原则,还是扁平化和可读性更重要?
EAFP 在很多情况下都是一个合理的格言,但它不是一个可以盲目遵循的格言。在你的例子中,我会说 if/elif 版本没有什么可怕的错误。
这两个版本都涉及代码重复,因此如果您要处理大量情况,可能会变得笨拙。一种处理方法是将 dict/function 对拉出到一个列表中,然后遍历该列表:
handlers = [ (dict1, do_stuff_dict1), (dict2, do_stuff_dict2), (dict3, do_stuff_dict3) ]
for whichDict, whichFunc in handlers:
try:
val = whichDict[key]
except KeyError:
continue
else:
whichFunc()
break
else:
do_stuff_not_found()
我更喜欢使用 dict.get(key, default_value) 来避免异常处理,例如:
handlers = [(d1, func_1), (d2, func_2)]
handlers_found = [(d, func) for d, func in handlers if d.get(key)]
if handlers_found:
handlers_found[0][1]()
else:
do_stuff_not_found()
get(key[, default])
Return the value for key if key is in the
dictionary, else default. If default is not given, it defaults to
None, so that this method never raises a KeyError.
https://docs.python.org/2/library/stdtypes.html
我正在尝试熟悉 Python 的最佳实践。根据 Python 的禅宗,请求宽恕比请求许可更容易,但是,它也说平面优于嵌套和可读性。你会如何处理这个问题:
我有3本词典。我有一把钥匙,我想测试钥匙是否在字典中。钥匙只会在其中之一。根据它所在的字典,我想做不同的事情。
使用try/except,我得出以下解决方案:
try:
val = dict1[key]
except KeyError:
try:
val = dict2[key]
except KeyError:
try:
val = dict3[key]
except KeyError:
do_stuff_key_not_found()
else:
do_stuff_dict3()
else:
do_stuff_dict2()
else:
do_stuff_dict1()
根据 Python 的 EAFP 原则,这将是可行的方法,但它看起来很杂乱,而且可读性不是很好。
一个更简单的解决方案是:
if key in dict1:
val = dict1[key]
do_stuff_dict1()
elif key in dict2:
val = dict2[key]
do_stuff_dict2()
elif key in dict3:
val = dict3[key]
do_stuff_dict3()
else:
do_stuff_key_not_found()
处理这种情况更Pythonic的方法是什么?我应该坚持 EAFP 原则,还是扁平化和可读性更重要?
EAFP 在很多情况下都是一个合理的格言,但它不是一个可以盲目遵循的格言。在你的例子中,我会说 if/elif 版本没有什么可怕的错误。
这两个版本都涉及代码重复,因此如果您要处理大量情况,可能会变得笨拙。一种处理方法是将 dict/function 对拉出到一个列表中,然后遍历该列表:
handlers = [ (dict1, do_stuff_dict1), (dict2, do_stuff_dict2), (dict3, do_stuff_dict3) ]
for whichDict, whichFunc in handlers:
try:
val = whichDict[key]
except KeyError:
continue
else:
whichFunc()
break
else:
do_stuff_not_found()
我更喜欢使用 dict.get(key, default_value) 来避免异常处理,例如:
handlers = [(d1, func_1), (d2, func_2)]
handlers_found = [(d, func) for d, func in handlers if d.get(key)]
if handlers_found:
handlers_found[0][1]()
else:
do_stuff_not_found()
get(key[, default]) Return the value for key if key is in the dictionary, else default. If default is not given, it defaults to None, so that this method never raises a KeyError. https://docs.python.org/2/library/stdtypes.html