I want to write a wrapper class which takes a value and behaves just like it except for adding a 'reason' attribute. I had something like this in mind:
class ExplainedValue(object):
def __init__(self, value, reason):
self.value = value
self.reason = reason
def __getattribute__(self, name):
print '__getattribute__ with %s called' % (name,)
if name in ('__str__', '__repr__', 'reason', 'value'):
return object.__getattribute__(self, name)
value = object.__getattribute__(self, 'value')
return object.__getattribute__(value, name)
def __str__(self):
return "ExplainedValue(%s, %s)" % (
str(self.value),
self.reason)
__repr__ = __str__
However, the double-underscore functions don't seem to be captured with __getattribute__
, for example:
>>> numbers = ExplainedValue([1, 2, 3, 4], "it worked")
>>> numbers[0]
Traceback (most recent call last):
File "<pyshell#118>", line 1, in <module>
numbers[0]
TypeError: 'ExplainedValue' object does not support indexing
>>> list(numbers)
__getattribute__ with __class__ called
Traceback (most recent call last):
File "<pyshell#119>", line 1, in <module>
list(numbers)
TypeError: 'ExplainedValue' object is not iterable
I would think the two above should end up doing this:
>>> numbers.value[0]
__getattribute__ with value called
1
>>> list(numbers.value)
__getattribute__ with value called
[1, 2, 3, 4]
Why is this not happening? How can I make it happen? (This might be a horrible idea to actually use in real code but I'm curious about the technical issue now.)
__magic__
functions. These are set when the object (or the class) is created. Whenever the interpreter internally needs to call those functions it can call it directly instead of doing a lookup through thegetattr
mechanism. (Obviously you should verify this by downloading the source and looking for where this structure is defined.) – Devoteeoriginal_object.reason="because"
. But you probably know this already... – Recipience__getattribute__
also link to this.) – Devotee__getattribute__()
doesn't get called (and log a message before theTypeError
) when__getitem__()
is being looked up. – Devotee