Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Defining setter in a shorter way

Tags:

python

Currently when I want to define a setter and leave getter alone I do this:

@property
def my_property(self):
    return self._my_property

@my_property.setter
def my_property(self, value):
    value.do_some_magic()
    self._my_property = value

Is there any way to make it shorter? I'd like to skip this part as it always look the same:

@property
def my_property(self):
    return self._my_property
like image 238
Matt Avatar asked Sep 23 '14 08:09

Matt


1 Answers

There's no out of the box solution, but you can try something like this:

def defprop(name):
    def getter(self):
        return getattr(self, name)
    return property(getter)

class C(object):
    # ...
    my_dictionary = defprop('_my_dictionary')
    # ...

That does not save you that many keystrokes though, you still have to duplicate the attribute name. Besides it's less explicit.


Update: after thinking a bit, I've come up with this descriptor-based hackish trick (disclaimer: this is done just for a demonstration, I don't imply it's a good practice unless you have a damn good reason to do so):

class with_default_getter(object):
    def __init__(self, func):
        self._attr_name = '_{0.__name__}'.format(func)
        self._setter = func

    def __get__(self, obj, type):
        return getattr(obj, self._attr_name)

    def __set__(self, obj, value):
        return self._setter(obj, value)

Usage:

class C(object):
    @with_default_getter
    def my_property(self, value):
        print 'setting %s'
        self._my_property = value

>>> c = C()
>>> c.my_property = 123
setting 123
>>> c.my_property
123

This is pretty much the same as @georg suggests, just unfolds the implementation down to descriptors.

like image 183
bereal Avatar answered Sep 30 '22 02:09

bereal