简体   繁体   中英

How can I create a template function for setting object attributes in python?

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:

  1. Does this seem like a reasonable solution to this problem?
  2. Is there a better way to solve this in python?
  3. Would there be any side effects that I need to be aware of?

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM