我正在编写自己的容器,需要通过属性调用来访问内部的字典.容器的典型用法如下:
dict_container = DictContainer()
dict_container['foo'] = bar
...
print dict_container.foo
Run Code Online (Sandbox Code Playgroud)
我知道写这样的东西可能是愚蠢的,但这是我需要提供的功能.我正在考虑以下列方式实现它:
def __getattribute__(self, item):
try:
return object.__getattribute__(item)
except AttributeError:
try:
return self.dict[item]
except KeyError:
print "The object doesn't have such attribute"
Run Code Online (Sandbox Code Playgroud)
我不确定嵌套的try/except块是否是一个好习惯,所以另一种方法是使用hasattr()
和has_key()
:
def __getattribute__(self, item):
if hasattr(self, item):
return object.__getattribute__(item)
else:
if self.dict.has_key(item):
return self.dict[item]
else:
raise AttributeError("some customised error")
Run Code Online (Sandbox Code Playgroud)
或者使用其中一个和一个尝试catch块,如下所示:
def __getattribute__(self, item):
if hasattr(self, item):
return object.__getattribute__(item)
else:
try:
return self.dict[item]
except KeyError:
raise AttributeError("some customised error")
Run Code Online (Sandbox Code Playgroud)
哪个选项最pythonic和优雅?
lqc*_*lqc 152
你的第一个例子非常好.即使是官方的Python文档也推荐这种称为EAFP的风格.
就个人而言,我更喜欢在没有必要时避免嵌套:
def __getattribute__(self, item):
try:
return object.__getattribute__(item)
except AttributeError:
pass # fallback to dict
try:
return self.dict[item]
except KeyError:
raise AttributeError("The object doesn't have such attribute") from None
Run Code Online (Sandbox Code Playgroud)
PS.has_key()
已经在Python 2中被弃用了很长时间.请item in self.dict
改用.
Bru*_*ado 15
虽然在Java中使用Exceptions进行流控制确实是一种不好的做法(主要是因为异常迫使jvm收集资源(这里更多)),在Python中你有两个重要的原则:Duck Typing和EAFP.这基本上意味着我们鼓励您尝试以您认为可行的方式使用对象,并在事情不那样时进行处理.
总之,唯一的问题是你的代码得到了太多的缩进.如果您愿意,可以尝试简化一些嵌套,如lqc建议的那样
对于您的具体示例,您实际上不需要嵌套它们.如果try
块中的表达式成功,则函数将返回,因此只有在第一次尝试失败时才会运行整个try/except块之后的任何代码.所以你可以这样做:
def __getattribute__(self, item):
try:
return object.__getattribute__(item)
except AttributeError:
pass
# execution only reaches here when try block raised AttributeError
try:
return self.dict[item]
except KeyError:
print "The object doesn't have such attribute"
Run Code Online (Sandbox Code Playgroud)
嵌套它们并不坏,但我觉得保持平整使结构更清晰:你依次尝试一系列的东西并返回第一个有效的东西.
顺便说一下,您可能想要考虑是否真的想要使用__getattribute__
而不是在__getattr__
这里.使用__getattr__
将简化操作,因为您将知道正常的属性查找过程已经失败.
嵌套 try/except 的一个简单的好例子如下:
import numpy as np
def divide(x, y):
try:
out = x/y
except:
try:
out = np.inf * x / abs(x)
except:
out = np.nan
finally:
return out
Run Code Online (Sandbox Code Playgroud)
现在尝试各种组合,你会得到正确的结果:
divide(15, 3)
# 5.0
divide(15, 0)
# inf
divide(-15, 0)
# -inf
divide(0, 0)
# nan
Run Code Online (Sandbox Code Playgroud)
(当然,我们有 NumPy,所以我们不需要创建这个函数。)
在我看来,这将是处理它的最Python的方式,但因为它使你的问题没有实际意义.请注意,这个定义__getattr__()
的,而不是__getattribute__()
因为这样做意味着它只有应对"特殊"属性被保留在内部字典.
def __getattr__(self, name):
"""only called when an attribute lookup in the usual places has failed"""
try:
return self.my_dict[name]
except KeyError:
raise AttributeError("some customized error message")
Run Code Online (Sandbox Code Playgroud)
请注意-在这种情况下,首先finally
要碰到,但也会跳过。
def a(z):
try:
100/z
except ZeroDivisionError:
try:
print('x')
finally:
return 42
finally:
return 1
In [1]: a(0)
x
Out[1]: 1
Run Code Online (Sandbox Code Playgroud)
根据文档,最好通过元组或像这样处理多个异常:
import sys
try:
f = open('myfile.txt')
s = f.readline()
i = int(s.strip())
except IOError as e:
print "I/O error({0}): {1}".format(e.errno, e.strerror)
except ValueError:
print "Could not convert data to an integer."
except:
print "Unexpected error: ", sys.exc_info()[0]
raise
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
143250 次 |
最近记录: |