我必须写一个覆盖__getattribute__
的某种类。
基本上我的类是一个容器,它将每个用户添加的属性保存到self._meta
这是一个字典。
class Container(object):
def __init__(self, **kwargs):
super(Container, self).__setattr__('_meta', OrderedDict())
#self._meta = OrderedDict()
super(Container, self).__setattr__('_hasattr', lambda key : key in self._meta)
for attr, value in kwargs.iteritems():
self._meta[attr] = value
def __getattribute__(self, key):
try:
return super(Container, self).__getattribute__(key)
except:
if key in self._meta : return self._meta[key]
else:
raise AttributeError, key
def __setattr__(self, key, value):
self._meta[key] = value
#usage:
>>> a = Container()
>>> a
<__main__.Container object at 0x0000000002B2DA58>
>>> a.abc = 1 #set an attribute
>>> a._meta
OrderedDict([('abc', 1)]) #attribute is in ._meta dictionary
我有一些继承Container
基类的类,他们的一些方法有@property装饰器。
class Response(Container):
@property
def rawtext(self):
if self._hasattr("value") and self.value is not None:
_raw = self.__repr__()
_raw += "|%s" %(self.value.encode("utf-8"))
return _raw
问题是.rawtext
无法访问。 (我得到了属性错误。)._meta
中的每个键都可以访问,__setattr__
基类的object
添加的每个属性都可以访问,但@property装饰器的方法到属性不是。我认为这与我在__getattribute__
基类中重写Container
的方式有关。我该怎么做才能使@property
的属性可以访问?
答案 0 :(得分:6)
我认为你应该考虑在这里查看__getattr__
而不是__getattribute__
。区别在于:如果__getattribute__
存在,则会被无条件地调用 - __getattr__
仅在python无法通过其他方式找到属性时被调用。
答案 1 :(得分:2)
我完全赞同mgilson。如果您想要一个与您的代码等效的示例代码,但您可以尝试使用属性:
class Container(object):
def __init__(self, **kwargs):
self._meta = OrderedDict()
#self._hasattr = lambda key: key in self._meta #???
for attr, value in kwargs.iteritems():
self._meta[attr] = value
def __getattr__(self, key):
try:
return self._meta[key]
except KeyError:
raise AttributeError(key)
def __setattr__(self, key, value):
if key in ('_meta', '_hasattr'):
super(Container, self).__setattr__(key, value)
else:
self._meta[key] = value
我真的不明白你的_hasattr
属性。你把它作为一个属性,但它实际上是一个可以访问self
的函数......它不应该是一个方法吗?
实际上我认为你应该简单地使用内置函数hasattr
:
class Response(Container):
@property
def rawtext(self):
if hasattr(self, 'value') and self.value is not None:
_raw = self.__repr__()
_raw += "|%s" %(self.value.encode("utf-8"))
return _raw
请注意,hasattr(container, attr)
也将True
返回_meta
。
令我困惑的另一件事是你使用OrderedDict
的原因。我的意思是,你迭代kwargs
,迭代有随机顺序,因为它是正常的dict
,并在OrderedDict
中添加项目。现在,您有_meta
,其中包含随机顺序的值。
如果您不确定是否需要订购特定订单,只需使用dict
,最后再转换为OrderedDict
。
顺便说一下:永远曾使用try: ... except:
而不指定要捕获的异常。在您的代码中,您实际上只想捕获AttributeError
,所以您应该完成:
try:
return super(Container, self).__getattribute__(key)
except AttributeError:
#stuff