Python: can I use a class-level decorator to add a mixin to the decorated class?

Viewed 92

I'd like to have a decorator that, among other stuff, adds a mixin to the class it's decorating. (I recognize that this may be a Really Bad Idea but bear with me.) The following almost works:

def add_mixin(cls):
   class inner(cls, NewMixin):
      pass
   return inner

Now if I do:

@add_mixin
class foo:
   ...bunch o' stuff...

class foo seems to work just fine, with NewMixin mixed in. (Maybe this scheme wouldn't exactly preserve the MRO of foo in the face of other superclasses but I don't think I care about that.)

The only problem I've found is that at this point foo.__name__ is "inner" and I'd like it to be "foo"! I can work around this by adding inner.__name__ = cls.__name__ in the definition of add_mixin and that seems to cover all the bases (as it were).

Question: Is there a better way to do this? Are there other lurking pitfalls here that I'm not seeing?

Thanks for any help.

1 Answers

Edit: The question was edited to mention this approach while I was writing the answer.

You can do:

def add_mixin(cls):
   class inner(cls, NewMixin):
      pass
   inner.__name__ = cls.__name__
   return inner

and then:

@add_mixin
class foo:
   pass

@add_mixin
class bar:
   pass

f = foo
print(f.__name__)
b = bar
print(b.__name__)
print(f.__name__)

gives

foo
bar
foo

(Printing foo a second time after referencing bar to demonstrate that __name__ isn't overwritten.)

In terms of pitfalls, that I'm not sure about.

Related