Reputation: 21951
Say my class already has __getattr__
and __setattr__
like so:
def __getattr__(self, attr):
return _global_user_data[self.userid][attr]
def __setattr__(self, attr, value):
_global_user_data[self.userid][attr] = value
I want to make it so that player's gold (for example) cannot drop below zero. Here's a setter for it:
def gold(self, value):
if value < 0:
raise ValueError
self.__setattr__('gold', value)
However, I find it stupid to write a getter which does nothing but calls for self.__getattr__('gold')
, is there a way to make it so I don't need do define yet an other method here?
It's not just one property (gold in this example), I have multiple properties and the getter seemS to be just some extra work.
Upvotes: 0
Views: 797
Reputation: 122161
If I've correctly understood what you're after (this time!) you could do something like:
class User:
def __init__(self, id_):
self.user_id = id_
def __getattr__(self, attr):
return _global_user_data[self.user_id][attr]
def set_x(self, val):
if val < 0:
raise ValueError
_global_user_data[self.user_id]['x'] = val
x = property(lambda self: self.__getattr__('x'), set_x)
You only need to define a specific setter for x
, the getter just redirects to the existing __getattr__
. Note that this creates the property
directly, rather than using the decorator syntax, but otherwise does exactly the same thing. In use:
>>> _global_user_data = {0: {'x': None}}
>>> user = User(0)
>>> user.x
>>> user.x = -1
Traceback (most recent call last):
File "<pyshell#38>", line 1, in <module>
user.x = -1
File "<pyshell#35>", line 8, in set_x
raise ValueError
ValueError
>>> user.x = 1
>>> user.x
1
Upvotes: 3