Reputation: 11628
Given following class, I can modify _x
using the setter/getter construct. But is it now possible to change _x
by calling a method?
The reason I'm asking is just because it would later be very convenient to define something as a lambda using lambda y: (c.x := y)
which works in 3.8, but in 3.7 we'd need something like lambda y: c.x.some_method_maybe(y)
.
class C:
def __init__(self):
self._x = 0
@property
def x(self):
return self._x
@x.setter
def x(self,_x):
print(_x)
self._x = _x
c = C()
c.x = 999 # this works
c.x.some_method_maybe(999) # call setter of x explicitly?
Upvotes: 1
Views: 1035
Reputation: 123
You may take advantage of the property's fset attrybute by using something like the following:
C.x.fset(c, 999)
Upvotes: 1
Reputation: 21474
you can make the getter and setter normal methods then pack them into a property afterwards
class C:
def __init__(self):
self._x = 0
def get_x(self):
"getter for property x, see `help(C.x)`"
return self._x
def set_x(self,_x):
"setter for property x, see `help(C.x)`"
print(_x)
self._x = _x
x = property(get_x,set_x, doc="""\
documentation of property x here,
`help(C.x)` will print this""")
then you can use c.set_x
as your callback and the property c.x
still works as you expect.
But notice that the method was totally allowed to do self._x = _x
because it was a function instead of a lambda so you could just do the same where you need a callback:
def modify(y): c.x = y
As long as you are ok defining your lambda on it's own line this is always a valid design pattern, to just declare a short function for your callbacks.
Alternatively if you love one liners and lambdas and hate readability you can use the __set__
magic method of the property on the class itself if you don't want to expose the setter directly.
modify = lambda val: type(c).x.__set__(c, val)
where type(c)
gets the class object, .x
gives the property object directly, .__set__
is the magic method called when you set the property of an instance, and you call it with the instance as the first argument as you'd expect calling methods on classes to work.
Upvotes: 3