python reference a property like a function
How do you pythonically set multiple properties without referencing them individually? Below is my solution.
class Some_Class(object): def __init__(self): def init_property1(value): self.prop1 = value def init_property2(value): self.prop2 = value self.func_list = [init_property1, init_property2] @property def prop1(self): return 'hey im the first property' @prop1.setter def prop1(self, value): print value @property def prop2(self): return 'hey im the second property' @prop2.setter def prop2(self, value): print value class Some_Other_Class(object): def __init__(self): myvalues = ['1 was set by a nested func','2 was set by a nested func'] some_class= Some_Class() # now I simply set the properties without dealing with them individually # this assumes I know how they are ordered (in the list) # if necessary, I could use a map for idx, func in enumerate(some_class.func_list): func(myvalues[idx]) some_class.prop1 = 'actually i want to change the first property later on' if __name__ == '__main__': test = Some_Other_Class()
this became necessary to do when I had many many properties to initialize with user defined values. My code otherwise would look like a giant list of setting each property individually (very messy).
Note that many people have good answers below and I think I have reached a good solution. This is a re-edit mostly trying to clearly state the question. But, if anyone has a better approach please share!
just use the @property decorator
>>> class A: ... a=2 ... @property ... def my_val(self,val=None): ... if val == None:return self.a ... self.a = val ... >>> a=A() >>> a.my_val 2 >>> a.my_val=7 >>> a.my_val 7
something like this?
if you only want to allow setting then dont give it a default val
>>> class A: ... a=2 ... @property ... def my_val(self,val): ... self.a = val ... >>> a=A() >>> a.my_val <Exception> >>> a.my_val=7 >>> a.a 7
or if you only want to allow retrieval just ommit the 2nd arg
>>> class A: ... a=2 ... @property ... def my_val(self): ... return self.a ... ... >>> a=A() >>> a.my_val 2 >>> a.my_val=7 <Exception>
I ... finally think I know what you're trying to do, and you don't need to do it the way you're approaching it. Let me take a stab at this.
class someclass(object): def __init__(self): func_list = [self.setter1, self.setter2] value_list = [1, 2] # These lines don't need to be this complicated. # for ind in range(len(func_list)): # func_list[ind](value_list[ind]) for idx, func in enumerate(func_list): func(value_list[idx]) # Or even better for idx, (func, val) in enumerate(zip(func_list, value_list)): func(val) def setter1(self, value): self.a = value def setter2(self, value): self.b = value
It's worth pointing out that the idx variable and enumerate calls are superfluous in the second form, but I wasn't sure if you need that elsewhere.
If you look up the property in the object dict, you will get the property descriptor (if any), and likewise with the class; e.g.
a = SomeClass() descriptor = a.__dict__.get('descriptor', type(a).__dict__.get('descriptor'))
Assuming that descriptor is a descriptor, it will have the following methods:
['deleter', 'fdel', 'fget', 'fset', 'getter', 'setter']
Note the fget and fset.