以更短的方式定义setter

时间:2014-09-23 08:29:22

标签: python

目前,当我想要定义一个setter并单独留下getter时,我会这样做:

@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

有没有办法缩短它?我想跳过这部分,因为它总是看起来一样:

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

4 个答案:

答案 0 :(得分:6)

没有开箱即用的解决方案,但你可以尝试这样的事情:

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

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

虽然这不会为您节省很多次击键,但仍需要复制属性名称。除此之外它不那么明确。


更新:经过一番思考,我已经提出了这种基于描述符的黑客技巧(免责声明:这只是为了演示,我并不暗示它和#39;除非你有充分的理由这样做,否则这是一种很好的做法):

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)

用法:

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

这与@georg建议的几乎相同,只是将实现展开到描述符。

答案 1 :(得分:5)

您可以按照下划线约定制作一个自动创建getter的装饰器:

def setter(fn):
    def _get(self):
        return getattr(self, '_' + fn.__name__)
    def _set(self, val):
        return fn(self, val)
    return property(_get, _set)

或更简洁,如果您更喜欢这种风格:

def setter(fn):
    return property(
        lambda self: getattr(self, '_' + fn.__name__),
        fn)

用法:

class X(object):
    @setter
    def my_property(self, value):
        self._my_property = value + 1

x = X()
x.my_property = 42
print x.my_property # 43

答案 2 :(得分:1)

没有我所知道的捷径 - 记住显式优于隐式(来自蟒蛇的Zen)。

可能在你的代码到目前为止,属性总是那样 - 但你可以在某个时候写一个属性getter来取一个完全计算的值 - 在这种情况下你的属性getter和setter看起来不像那样所有

如果您愿意,可以写一个包装器,它可以将这些简单的默认方法作为包装器的一部分提供。

答案 3 :(得分:1)

def set_my_property(self, value):
    value.do_some_magic()
    self._my_property = value

my_property = property(fset=set_my_property)