I am working on a project where I need to check if a value being set is a part of a specific set of values. The exact same check needs to happen for a whole bunch of attributes, so I would like to setup some sort of template function that can be called whenever any of them is set. I looked at using the @property decorator, but that would require a lot of duplicate code, and is very verbose. So, I came up with a way to do it using python's property function and some functions that return functions:
class MyClass(object):
style_types = ("FOO", "BAR", "NONE")
def __init__(self):
self._style_a = "NONE"
self._style_b = "NONE"
self.name = None
def get_tmpl(attr):
def get_attr(self):
return getattr(self, attr)
return get_attr
def set_tmpl(attr):
def set_attr(self, val):
if val.upper() in style_types:
setattr(self, attr, val.upper())
else:
setattr(self, attr, "NONE")
return set_attr
def del_tmpl(attr):
def del_attr(self):
delattr(self,attr)
return del_attr
style_a = property( get_tmpl("_style_a"), set_tmpl("_style_a"), del_tmpl("_style_a") )
style_b = property( get_tmpl("_style_b"), set_tmpl("_style_b"), del_tmpl("_style_b") )
Input:
c = MyClass()
print "style_a = " + c.style_a + ", style_b = " + c.style_b
c.style_a = "FOO"
c.style_b = "bad"
print "style_a = " + c.style_a + ", style_b = " + c.style_b
Output:
style_a = NONE, style_b = NONE
style_a = FOO, style_b = NONE
So, basically I am creating some functions that return functions and passing in which attributes they should be used on. I can then build a generic set_attr function that can be used as a template for all of these attributes.
My questions are:
Try using __setattr__
. It has less magic than functions which return functions and looks more readable, imho. Here is your example written with __setattr__
class MyClass(object):
style_types = ("FOO", "BAR", "NONE")
def __init__(self):
self.style_a = "NONE"
self.style_b = "NONE"
self.not_style_c = "bad"
def __setattr__(self, name, value):
if name.startswith('style'):
if value.upper() in self.style_types:
object.__setattr__(self, name, value.upper())
else:
object.__setattr__(self, name, "NONE")
else:
object.__setattr__(self, name, value)
c = MyClass()
print("style_a = " + c.style_a + ", style_b = " + c.style_b + ", not_style_c = " + c.not_style_c)
c.style_a = "FOO"
c.style_b = "bad"
c.not_style_c = "good"
print("style_a = " + c.style_a + ", style_b = " + c.style_b + ", not_style_c = " + c.not_style_c)
Side effects: be careful of using setattr
in __setattr__
, you may fall into infinite recursion. That's why object.__setattr__(self, name, value)
is used.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.