Can I run an operation on an object's attribute when reading?

Steven D'Aprano steve at REMOVE-THIS-cybersource.com.au
Mon Jan 19 08:19:10 EST 2009


On Mon, 19 Jan 2009 04:04:23 -0800, Phillip B Oldham wrote:

> Is it possible to automatically run an operation on a object's attribute
> when reading? For instance, if I have the following:
> 
> class Item(object):
>   tags = ['default','item']
> 
> item = Item()
> 
> desc = item.tags
> 
> When I'm reading the item.tags, I'd like to automagically have the value
> converted to a string, eg: "default item". I know I could write a getter
> to do this for me, but I'd like to avoid that if possible on this
> occasion.

When all you have is a hammer, everything looks like a nail... Why do you 
have to read item.tags directly? Just write a function and call it 
instead of direct attribute access. This is the simplest, easiest 
solution with the fewest side-effects.

def get_tags(item):
    return ' '.join(item.tags)

desc = get_tags(item)


If you don't like that solution, monkey-patch the class with a getter:

@property
def tags(self):
    return " ".join(self._tags)

Item._tags = Item.tags
Item.tags = tags

This is dangerous, because other classes may expect Item.tags to be a 
list. Better to create your own accessor method:

def get_tags(self):
    return " ".join(self.tags)

Item.get_tags = get_tags

item = Item()
desc = item.get_tags()


If you don't like monkey-patching (and you probably shouldn't), then 
write a proxy class that delegates to the original:


_Item = Item
class Item(object):
    def __init__(self, *args):
        self.__dict__['_item'] = _Item(*args)
    @property
    def tags(self):
        return ' '.join(self._item.tags)
    def __getattr__(self, attr):
        return getattr(self._item, attr)
    def __setattr__(self, attr, value):
        setattr(self._item, attr, value)


I dare say there's a metaclass solution too, but I'm not crazy enough to 
do that.



-- 
Steven



More information about the Python-list mailing list