简体   繁体   中英

How to write proper decorator to alter classes

I know I can use closure and inheritance to create a decorator that alter classes.

def wrapper(cls, *args, **kwargs):
    class Wrapped(cls):
        """Modify your class here."""

    return Wrapped

But if I need to test my new classes to know if they inherit Wrapped or not, I can't access Wrapped itself to do a straightforward isinstance or issubclass test.

On the other hand, straightforward inheritance isn't an option. I have about 10 different wrapper which can need to be added to a class. That burden the hierarchy tree way too much.

So I need a way to access the closure from the outside. Or an alternative way to build decorator.

It sounds like you want to check whether a class has been wrapped by this particular decorator. The most efficacious method to do so may simply be to add a field to that effect, to wit:

def wrapper(cls, *args, **kwargs):
    class Wrapped(cls):
        """Modify your class here."""

    Wrapped._is_wrapped_by_this_wrapper = True
    return Wrapped

Then you can check hasattr and getattr of _is_wrapped_by_this_wrapper .

If you have multiple wrapper classes that work with each other you may be able to come up with a solution that works better together, eg perhaps a set consisting of all the names of the wrappers that have been applied.

You could inherit from two classes, a base class and cls :

class WrapperBase:
    pass

def wrapper(cls, *args, **kwargs):
    class Wrapped(cls, WrapperBase):
        """Modify your class here."""

    return Wrapped

Now all instances of generated classes test True for isinstance(obj, WrapperBase) .

Note that WrapperBase has no impact on finding inherited methods in the MRO; it comes dead last in any hierarchy (on Python 2, not inheriting from object puts it dead last in the MRO, in Python 3 it'll sit between object and whatever came before object in the MRO of the wrapped class.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM