4

I have a class like this:

class A:
    def __init__(self):
        self.size=0
    def change_size(self,new):
        self.size=new

I want to add an attribute to the change_size method to say what it changes - i.e. so that

A(blah)
blah.change_size.modifies

returns

'size'

is this possible? I have tried:

class A:
    def __init__(self):
        self.size=0
    def change_size(self,new):
        self.change_size.modifies = 'size'
        self.size=new

nope

class A:
    def __init__(self):
        self.size=0
        self.change_size.modifies = 'size'
    def change_size(self,new):
        self.size=new

nope

class A:
    def __init__(self):
        self.size=0
    def change_size(self,new,modifies='size'):
        self.size=new

none of which seem to work.

2
  • Possible duplicate of How to add property to a class dynamically? Commented Jan 8, 2018 at 6:37
  • 1
    The problem you're running into is that self.change_size is a wrapper that passes self to the method, not the method itself. You'll need to do this through the class, not an instance. Commented Jan 8, 2018 at 6:50

2 Answers 2

3

That's simple enough. It goes basically the same way you'd add attributes to any other function:

class A:
    def __init__(self):
        self.size=0
    def change_size(self,new):
        self.size=new
    change_size.modifies = 'size'

print(A.change_size.modifies) # prints size
Sign up to request clarification or add additional context in comments.

1 Comment

well damn... that was simple! You've solved my problem so fast here that I have to wait before I'm allowed to mark your answer as correct haha
3

A more universal solution with a help decorator.

from functools import wraps

def attributes(**attrs):
    def decorator(f):
        @wraps(f)
        def wrapper(*args, **kwargs):
            return f(*args, **kwargs)

        for attr_name, attr_value in attrs.items():
            setattr(wrapper, attr_name, attr_value)

        return wrapper

    return decorator

and rewrite you class as

class A:
    def __init__(self):
        self.size = 0

    @attributes(modifies='size')
    def change_size(self, new):
        self.size = new

3 Comments

My answer is not setting a class attribute. Setting a class attribute would be something like change_size_modifies = 'size' at class scope instead of change_size.modifies = 'size'. Also, the wrapper in your decorator is unnecessary (you could just set the attributes on the original f and return f), and your syntax is invalid; you shouldn't quote modifies.
Thanks for reminding the syntax error, the previous answer is updated.
Your wrapper is passing the wrong arguments to f; it should be f(*args, **kwargs), not f(args, kwargs).

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.