I have a class with many parameters that are stored in a dictionary as below (in practice, it's a bit more complex, but this gives a good idea). I am able to 'autogenerate' get and set methods using partialmethod
:
for a_name in ['x', 'y', 'z']:
locals()["get_" + a_name] = partialmethod(_get_arg,
arg_name=a_name)
locals()["set_" + a_name] = partialmethod(_set_arg,
arg_name=a_name)
Ideally, I wanted to use @property
, but only if I can 'autogenerate' @property
, @setter
and @deleter
. Would it be possible? The second snippet show the 'manually' added properties; I am looking into using an equivalent of partialmethod
to avoid repetition and unmaintainable code.
class C:
def __init__(self):
self.kwargs = {'x' : 0, 'y' : 3, 'z' : True}
def __get_arg(self, arg_name):
assert arg_name in self.kwargs
return self.kwargs[arg_name]
def __set_arg(self, arg_name, value):
assert arg_name in self.kwargs
self.kwargs[arg_name] = value
def __del_arg(self, arg_name):
assert arg_name in self.kwargs
del self.kwargs[arg_name]
@property
def x(self):
return self.__get_arg('x')
@x.setter
def x(self, value):
self.__set_arg('x', value)
@x.deleter
def x(self):
self.__del_arg('x')
@property
def y(self):
return self.__get_arg('y')
@y.setter
def y(self, value):
self.__set_arg('y', value)
@y.deleter
def y(self):
self.__del_arg('y')
@property
def z(self):
return self.__get_arg('z')
@x.setter
def z(self, value):
self.__set_arg('z', value)
@x.deleter
def z(self):
self.__del_arg('z')
c = C()
c.x = 'foo' # setter called
foo = c.x # getter called
del c.x # deleter called
You can write your own descriptor type, and use the __set_name__
method that will get called on it (by the class creation machinery) to figure out what name it's been saved to in the class:
class MyProp:
def __set_name__(self, owner, name):
self.name = name
def __get__(self, instance, owner=None):
if instance is None:
return self
return instance._get_arg(self.name)
def __set__(self, instance, value):
instance._set_arg(self.name, value)
def __delete__(self, instance):
instance._del_arg(self.name)
You'd use it this way:
class C:
# define __init__, _get_arg, etc.
x = MyProp()
y = MyProp()
z = MyProp()
Note that because it's code from another class calling the _X_arg
methods, you probably don't want to do name mangling, so I've changed the __
prefixes to just a single _
.