Python class @property: use setter but evade getter?

Don’t use a property in this case. A property object is a data descriptor, which means that any access to instance.var will invoke that descriptor and Python will never look for an attribute on the instance itself.

You have two options: use the .__setattr__() hook or build a descriptor that only implements .__set__.

Using the .__setattr__() hook

class MyClass(object):
    var="foo"

    def __setattr__(self, name, value):
        if name == 'var':
            print "Setting var!"
            # do something with `value` here, like you would in a
            # setter.
            value="Set to " + value
        super(MyClass, self).__setattr__(name, value)

Now normal attribute lookups are used when reading .var but when assigning to .var the __setattr__ method is invoked instead, letting you intercept value and adjust it as needed.

Demo:

>>> mc = MyClass()
>>> mc.var
'foo'
>>> mc.var="bar"
Setting var!
>>> mc.var
'Set to bar'

A setter descriptor

A setter descriptor would only intercept variable assignment:

class SetterProperty(object):
    def __init__(self, func, doc=None):
        self.func = func
        self.__doc__ = doc if doc is not None else func.__doc__
    def __set__(self, obj, value):
        return self.func(obj, value)

class Foo(object):
    @SetterProperty
    def var(self, value):
        print 'Setting var!'
        self.__dict__['var'] = value

Note how we need to assign to the instance .__dict__ attribute to prevent invoking the setter again.

Demo:

>>> f = Foo()
>>> f.var="spam"
Setting var!
>>> f.var="ham"
Setting var!
>>> f.var
'ham'
>>> f.var="biggles"
Setting var!
>>> f.var
'biggles'

Leave a Comment