1

For exmaple:

class person():
    def __init__(self):
        self.a1 = 0
        self.a2 = 0
        self.a3 = 0

    def method_a1(self):
        self.a1 = self.a1 * 2
        print(self.a1)

    def method_a2(self):
        self.a2 = self.a2 * 2
        print(self.a2)

    def method_a3(self):
        self.a3 = self.a3 * 2
        print(self.a3)

The three methods are similar, so I want to build a function to generate these methods, like this:

class person():
    def __init__(self):
        self.a1 = 0
        self.a2 = 0
        self.a3 = 0

   def method(p):
       p = p * 2
       print(p)

   method(self.a1)
   method(self.a2)
   method(self.a3)

I do not know how to write it.

SCB
  • 5,821
  • 1
  • 34
  • 43
Lin
  • 11
  • 2

3 Answers3

2

You could do sth along the following lines:

def _helper(attr):
    def method(self):
        val = getattr(self, attr) * 2
        setattr(self, attr, val)
        print(val)
    return method

class person():
    # ...
    method_a1 = _helper('a1')
    method_a2 = _helper('a2')
    method_a3 = _helper('a3')
user2390182
  • 72,016
  • 6
  • 67
  • 89
  • Feel this is the best way presented. Actually makes class methods (which actually have `self`) instead of attributes that are empty functions. – SCB Jan 04 '18 at 08:04
  • Yup, the effect is the same for most purposes, but you are creating the function objects only once for the class (class method is maybe not the right term as it is already used for sth else) and not for each instance. It is also a little more elegant if you don't have to hook into the `__init__`. – user2390182 Jan 04 '18 at 08:10
1

You could assign them straight in the __init__, and use some generic function that retrieves the attributes via string with getattr() and setattr(), and returns the function to call:

class person():
    def __init__(self):
        self.a1 = 0
        self.a2 = 0
        self.a3 = 0

        self.method_a1 = self._generic_update('a1')
        self.method_a2 = self._generic_update('a2')
        self.method_a3 = self._generic_update('a3')

    def _generic_update(self, attribute):
        def update():
            value = getattr(self, attribute)
            setattr(self, attribute, value * 2)
            print(getattr(self, attribute)
        return update
SCB
  • 5,821
  • 1
  • 34
  • 43
  • I like this one better than my answer **:-D** (particularly because of the assignment to `method_a1`, `method_a2`)... – Savir Jan 04 '18 at 07:58
  • 1
    Though you are correct, any case where you've got to start pulling out `getattr` and `setattr`, things are going to start getting confusing. Use as last resort. – SCB Jan 04 '18 at 08:00
0

There is a loooot of weird stuff you can do with Python.

One that comes to mind is using getattr (to fetch an attribute from a string representing its name) and setattr (to write an attribute using its name)

Check this out:

class Person(object):
    def __init__(self):
        self.a1 = 0
        self.a2 = 1
        self.a3 = 2

    def method(self, attr_name):
        new_value = getattr(self, attr_name) * 2
        setattr(self, attr_name, new_value)
        print(getattr(self, attr_name))


if __name__ == "__main__":
    pers = Person()
    pers.method('a1')
    pers.method('a2')
    pers.method('a3')

Outputs:

0
2
4

However: You should also consider readability: Sometimes writing a bit more can make other people who read your code understand it much better. Abusing things like this can make the code very confusing very fast.

Savir
  • 17,568
  • 15
  • 82
  • 136