17

I want to apply a decorator to every method in a class. I don't have source code of the class, so I can't directly apply the decorator. I want to call some function that accepts the class and adds the decorators.

But the problem is testclass.__dict__ is a mappingproxy object and it doesn't support any assignment or modification, directly at least. So the question is how to avoid that restriction and apply decorator?

Here is code of the failed attempt:

class qwer:
    def test(self):
        print('test')

def decor(func):
    def w(*args, **named_args):
        print('decor')
        func(*args, **named_args)
    return w

qwer.__dict__['test'] = decor(qwer.__dict__['test'])

Error:

TypeError: 'mappingproxy' object does not support item assignment
QNA
  • 1,047
  • 2
  • 14
  • 26

1 Answers1

22

Use setattr to set an attribute on a class:

>>> setattr(qwer, 'test', decor(qwer.__dict__['test']))
>>> qwer.test
<function decor.<locals>.w at 0xb5f10e3c>

Demo:

>>> class A:                 
    pass
... 
>>> A.__dict__['foo'] = 'bar'
Traceback (most recent call last):
  File "<ipython-input-117-92c06357349d>", line 1, in <module>
    A.__dict__['foo'] = 'bar'
TypeError: 'mappingproxy' object does not support item assignment

>>> setattr(A, 'foo', 'bar')
>>> A.foo
'bar'
jkr
  • 17,119
  • 2
  • 42
  • 68
Ashwini Chaudhary
  • 244,495
  • 58
  • 464
  • 504