Python decorators for classes to include class identity

62 Views Asked by At

Basically I have a Base class and a metaclass and a ton of classes that use both I want to avoid doing class Name(Base, metaclass=Meta) over and over again and instead do this

@deco
class Name:

I already have a decorator like this:

def deco(cls):
    return Meta(cls.__name__, (Base, cls), dict(vars(cls)))

and it works, the problem is that its erasing the identity of the original class, for example:

  • when hovering over a variable of that class, vscode says its a _class_Meta object and not a Name object

  • print(Name().__doc__) works as expected but hovering over said objects doesn't show any docstring

  • functions and variables of the Name and the Base classes are not even recognized by vscode at all, only attributes of the metaclass

Im basically looking for something like the functools.wraps decorator

2

There are 2 best solutions below

0
DerSchinken On

Why this is happening and why you shouldn't do this in the first place:
You are getting no docstrings from vscode since this is quite hacky and thus vscode doesn't understand it, because it's very unpythonic, so it can't show you corect tooltips.
Always remember: Explicit is better than implicit. - The Zen of Python (read it yourself: import this). And it's not even worth it, it just makes your code more complex and less readable/understandable, and yes, even for yourself.

1
blhsing On

You can create a new base class with Base as the base class and Meta as the metaclass, so other classes can inherit from the new base class instead:

class Meta(type):
    def __call__(cls):
        print('new instance')
        return super().__call__()

class Base:
    def __init__(self):
        print('base')

class NewBase(Base, metaclass=Meta):
    pass

class Name(NewBase):
    pass

print(Name())

This outputs:

new instance
base
<__main__.Name object at 0x1467a61a4b80>

Demo: https://ideone.com/UOfMzv