0

I want to make use of properties in python while still being able to call the setter method of a property directly in some cases. The reason being, that I need to assign variables in lambda statements while using PySide/PyQt.

The following example includes two classes which should behave almost identical. One using property() and one @property.

class Test1:
    def __init__(self):
        self._x = 0

    def setx(self, value):
        print(f'x set to {value}')
        self._x = value

    x = property(fset=setx)


class Test2:
    def __init__(self):
        self._x = False

    @property
    def x(self):
        return self._x

    @x.setter
    def x(self, value):
        print(f'x set to {value}')
        self._x = value


t1 = Test1()
print('Test1:')
t1.x = 1
setattr(t1, 'x', 2)
t1.setx(3)


t2 = Test2()
print('Test2:')
t2.x = 1
setattr(t2, 'x', 2)

This works pretty well. For class Test1 i can assign values to the variable using 3 different ways. 2 of them are possible to use in a lambda statement.

However, if I'm using the @property decorator I only have 2 ways left (As far as I can see at least!). And the only possible way to assign in a lambda statement is using setattr, which I'd rather avoid since it hurts readability in my opinion :(

Question

Is there a way to use the syntactic sugar of the @property decorator while still being able to use the setter directly?

ekhumoro
  • 115,249
  • 20
  • 229
  • 336
johnson
  • 3,729
  • 3
  • 31
  • 32
  • 1
    _"The reason being, that I need to assign variables in lambda statements"_ That's not a good reason. 1) You can use a real function instead of a lambda. 2) There's [`setattr`](https://docs.python.org/3/library/functions.html#setattr). – Aran-Fey Mar 28 '18 at 10:03
  • @Aran-Fey: 1) I don't really want to use real functions because I have dozens of those assignments and this would bloat my code tremendously. 2) A tiny bit ugly in my opinion, but true nevertheless :) – johnson Mar 28 '18 at 10:40
  • @johnson. Surely getter/setter methods would *decrease* the bloat, since there would be no need for decorators. I also think they are much more effective and readable in pyqt/pyside programs, because they can be used as slots and are consistent with the style of the existing qt apis. – ekhumoro Apr 01 '18 at 17:28

1 Answers1

4

Edit: actually, there is a way to do it

class C:
    def __init__(self):
        self._x = 4
    @property
    def x(self):
        return self._x
    @x.setter
    def x(self, x):
        self._x = x        

c = C()

c.x == 4

C.x.fset(c, 3)

c.x == 3

But this is far less readable than setattr so I wouldn't use it.


No there isn't. But you shouldn't expect there to be.

Complaining you now only have two different ways to do something is not a good argument.

Like @Aran-Fey said, you can use a real def function or setattr like in your example. It is not wrong to use these and anyone worth their salt in python will understand what is going on.

FHTMitchell
  • 11,793
  • 2
  • 35
  • 47
  • I'm not complaining, I'm rather trying to find out about every way possible before deciding which approach I like most and want to use in the future – johnson Mar 28 '18 at 10:43
  • fset is the only thing that worked for me. When I used setattr in a lamba it kept calling the getter. – Greg Harley Nov 24 '19 at 02:44