1

Say we have 10 attributes:

class test(object):
  def __init__(self,a,b,c,d,e,f,g,h,i,j):
    self._a = a
    #the same with the rest of variables

Is it possible to make them all properties?:

@property
def a(self):
  return self.a
@a.setter
def a(self,a_new):
  #invoke other functions doing other stuff when attribute values change
  self._a = a_new

If I need the same functions to run when any instance attribute is changed, do I have to type the above code for each attribute? Is it possible to write the code once then use it as a custom decorator or something similar?

If the custom decorator is the way to go, can I afterwards override the setter function for some attributes?

0

1 Answer 1

1

If you really want all of your instance attributes to be properties you can implement __setattr__ and __getattribute__ methods. Here's a short demo:

class Test(object):
    attr_names = {'a', 'b', 'c', 'd'}

    def __init__(self, a, b, c, d):
        self.a = a
        self.b = b
        self.c = c
        self.d = d

    def __repr__(self):
        return 'Test({}, {}, {}, {})'.format(self.a, self.b, self.c, self.d)

    def __setattr__(self, name, value):
        if name in Test.attr_names:
            print('Setting {} to {}'.format(name, value))
            super().__setattr__(name, value)
        else:
            raise AttributeError("Can't set unknown attribute: " + name)

    def __getattribute__(self, name):
        if name in Test.attr_names:
            print('Getting {}'.format(name))
            return super().__getattribute__(name)
        else:
            raise AttributeError("Can't get unknown attribute: " + name)

t = Test(1, 2, 3, 4)
print(t)
t.b = 7
print(t)

try:
    t.e = 42
except AttributeError as err:
    print(err)

output

Setting a to 1
Setting b to 2
Setting c to 3
Setting d to 4
Getting a
Getting b
Getting c
Getting d
Test(1, 2, 3, 4)
Setting b to 7
Getting a
Getting b
Getting c
Getting d
Test(1, 7, 3, 4)
Can't set unknown attribute: e

This code is for Python 3. In Python 2 you will need to pass appropriate args to super:

super(Test, self)

eg,

super(Test, self).__setattr__(name, value)

Please see the data model docs for more information about these methods.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.