I had to write a class of some sort that overrides __getattribute__
.
basically my class is a container, which saves every user-added property to self._meta
which is a dictionary.
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
I have some classes which inherit Container
base class and some of their methods have @property decorator.
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
problem is that .rawtext
isn't accessible. (I get attributeerror.) every key in ._meta
is accessible, every attributes added by __setattr__
of object
base class is accessible, but method-to-properties by @property decorator isn't. I think it has to do with my way of overriding __getattribute__
in Container
base class. What should I do to make properties from @property
accessible?
I think you should probably think about looking at
__getattr__
instead of__getattribute__
here. The difference is this:__getattribute__
is called inconditionally if it exists --__getattr__
is only called if python can't find the attribute via other means.I completely agree with mgilson. If you want a sample code which should be equivalent to your code but work well with properties you can try:
I really do not understand your
_hasattr
attribute. You put it as an attribute but it's actually a function that has access toself
... shouldn't it be a method? Actually I think you should simple use the built-in functionhasattr
:Note that
hasattr(container, attr)
will returnTrue
also for_meta
.An other thing that puzzles me is why you use an
OrderedDict
. I mean, you iterate overkwargs
, and the iteration has random order since it's a normaldict
, and add the items in theOrderedDict
. Now you have_meta
which contains the values in random order. If you aren't sure whether you need to have a specific order or not, simply usedict
and eventually swap toOrderedDict
later.By the way: never ever use an
try: ... except:
without specifying the exception to catch. In your code you actually wanted to catch onlyAttributeError
s so you should have done: