将 python 装饰器应用于所有继承类

o_c*_*o_c 5 python django

在我的 django 项目中(django 1.6 - 很快升级到 1.9,python 2.7),

我想在我所有项目的模型类(20-30 个类)上应用装饰器。所有这些类都已经从一个名为“LinkableModel”的父类继承而来,这是我为某个(非相关)目的而编写的。

现在,我想对所有这些模型应用一个类装饰器。(具体来说,我指的是装饰器“python_2_unicode_compatible”:https ://docs.djangoproject.com/en/1.9/ref/utils/#django.utils.encoding.python_2_unicode_compatible )。

当我将此装饰器添加到其父类“LinkableModel”时,它不会被继承。有没有办法将装饰器应用于多个类,而不将其添加到每个类?

(理论上我什至不介意这个装饰器是否默认应用于我项目中的所有类......)

代码片段:

@python_2_unicode_compatible
class LinkableModel(models.Model):
    ...
    ...
    ...

class MyModel1(LinkableModel):
    ...
    ...
    ...

class MyModel2(LinkableModel):
    ...
    ...
    ...
Run Code Online (Sandbox Code Playgroud)

Yul*_*ova 6

在 Python 3.7 中,你现在可以这样做:

  class ParentClass:
      def __init_subclass__(cls, **kwargs):
          return your_decorator(_cls=cls)
Run Code Online (Sandbox Code Playgroud)

它将为 ParentClass 的每个子类应用装饰器

更新:完整示例:

def your_decorator(_cls):
    print("Hello, I'm decor!")
    def wrapper():
        return _cls()
    return wrapper


class ParentClass:
    def __init_subclass__(cls, **kwargs):
        return your_decorator(_cls=cls)


class A(ParentClass):
    pass

a = A()
Run Code Online (Sandbox Code Playgroud)


o_c*_*o_c 1

我使用了 @GingerPlusPlus 的答案,并创建了以下函数,将装饰器应用于类的所有子类:

 def apply_decorator_to_all_subclasses(globals_, base_class, decorator):
    """
    Given a 'globals_' dictionary, a base class, and a decorator - this function applies the decorator to all the defined classes that derive from the base class
    Note!: this function should be called only *after* the subclassess were declared
    :param globals_: the given output of globals(), in the caller's context
    :param base_class: the class whose descendants require the decorator
    :param decorator: the decorator to apply
    """
    for name, cls in globals_.items():
        # Applying only on *class* items, that are descandants of base_class
        if inspect.isclass(cls) and issubclass(cls, base_class) and cls != base_class:
            globals_[name] = decorator(cls)
Run Code Online (Sandbox Code Playgroud)