如何装饰一个类的所有函数,而不用为每个方法反复输入?[重复]

2025-03-04 08:27:00
admin
原创
70
摘要:问题描述:假设我的类有很多方法,我想在每个方法上应用我的装饰器,以后当我添加新方法时,我希望应用相同的装饰器,但我不想@mydecorator一直在方法声明上面写。如果我研究一下,__call__这是正确的做法吗?我想展示这种方法,对于以后发现此问题的任何人来说,这都是解决我的问题的类似方法,使用评论中提到的...

问题描述:

假设我的类有很多方法,我想在每个方法上应用我的装饰器,以后当我添加新方法时,我希望应用相同的装饰器,但我不想@mydecorator一直在方法声明上面写。

如果我研究一下,__call__这是正确的做法吗?


我想展示这种方法,对于以后发现此问题的任何人来说,这都是解决我的问题的类似方法,使用评论中提到的混合器。

class WrapinMixin(object):
    def __call__(self, hey, you, *args):
        print 'entering', hey, you, repr(args)
        try:
            ret = getattr(self, hey)(you, *args)
            return ret
        except:
            ret = str(e)
            raise
        finally:
            print 'leaving', hey, repr(ret)
    

然后你可以在另一个

class Wrapmymethodsaround(WrapinMixin): 
    def __call__(self, hey, you, *args):
         return super(Wrapmymethodsaround, self).__call__(hey, you, *args)

编者注:这个例子似乎解决的问题与所问的问题不同。


解决方案 1:

使用遍历类的属性并装饰可调用函数来装饰类。如果您有可调用的类变量,这可能是错误的做法,并且还会装饰嵌套类(感谢 Sven Marnach 指出这一点),但通常这是一个相当干净和简单的解决方案。示例实现(请注意,这不会排除特殊方法(__init__等),这些方法可能是或可能不是所需的):

def for_all_methods(decorator):
    def decorate(cls):
        for attr in cls.__dict__: # there's propably a better way to do this
            if callable(getattr(cls, attr)):
                setattr(cls, attr, decorator(getattr(cls, attr)))
        return cls
    return decorate

使用方式如下:

@for_all_methods(mydecorator)
class C(object):
    def m1(self): pass
    def m2(self, x): pass
    ...

解决方案 2:

尽管我不喜欢在使用明确的方法时使用神奇的方法,但您可能可以为此使用元类。

def myDecorator(fn):
    fn.foo = 'bar'
    return fn

class myMetaClass(type):
    def __new__(cls, name, bases, local):
        for attr in local:
            value = local[attr]
            if callable(value):
                local[attr] = myDecorator(value)
        return type.__new__(cls, name, bases, local)

class myClass(object):
    __metaclass__ = myMetaClass
    def baz(self):
        print self.baz.foo

并且它的工作方式就像每个可调用函数myClass都被修饰过一样myDecorator

>>> quux = myClass()
>>> quux.baz()
bar

解决方案 3:

不是为了起死回生,但我真的很喜欢德尔南的回答,但发现它确实有些欠缺。

def for_all_methods(exclude, decorator):
    def decorate(cls):
        for attr in cls.__dict__:
            if callable(getattr(cls, attr)) and attr not in exclude:
                setattr(cls, attr, decorator(getattr(cls, attr)))
        return cls
    return decorate

编辑:修复缩进

因此,您可以指定方法//属性//您不想装饰的东西

解决方案 4:

上述答案对我都不起作用,因为我还想修饰继承的方法,这无法通过使用来实现__dict__,而且我不想用元类让事情变得过于复杂。最后,我很乐意为 Python 2 提供一个解决方案,因为我只需要立即添加一些分析代码来测量类中所有函数所用的时间。

import inspect
def for_all_methods(decorator):
    def decorate(cls):
        for name, fn in inspect.getmembers(cls, inspect.ismethod):
            setattr(cls, name, decorator(fn))
        return cls
    return decorate

来源(略有不同的解决方案):https://stackoverflow.com/a/3467879/1243926
您还可以在那里看到如何为 Python 3 进行更改。

正如对其他答案的评论所建议的那样,请考虑使用inspect.getmembers(cls, inspect.isroutine)。如果您找到了一种适用于 Python 2 和 Python 3 并修饰继承方法的适当解决方案,并且仍然可以在 7 行内完成,请进行编辑。

解决方案 5:

您可以生成一个元类。这不会修饰继承的方法。

def decorating_meta(decorator):
    class DecoratingMetaclass(type):
        def __new__(self, class_name, bases, namespace):
            for key, value in list(namespace.items()):
                if callable(value):
                    namespace[key] = decorator(value)

            return type.__new__(self, class_name, bases, namespace)

    return DecoratingMetaclass

这将生成一个元类,用指定的函数装饰所有方法。你可以在 Python 2 或 3 中使用它,操作如下

def doubling_decorator(f):
    def decorated(*a, **kw):
        return f(*a, **kw) * 2
    return decorated

class Foo(dict):
    __metaclass__ = decorating_meta(doubling_decorator)

    def lookup(self, key):
        return self[key]

d = Foo()
d["bar"] = 5
print(d.lookup("bar")) # prints 10
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   3975  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   2742  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Freshdesk、ClickUp、nTask、Hubstaff、Plutio、Productive、Targa、Bonsai、Wrike。在当今快速变化的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多企业在项目管理过程中面临着诸多痛点,如任务分配不...
项目管理系统   80  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Monday、TeamGantt、Filestage、Chanty、Visor、Smartsheet、Productive、Quire、Planview。在当今快速变化的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多项目经理和团队在管理复杂项目时,常...
开源项目管理工具   88  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Smartsheet、GanttPRO、Backlog、Visor、ResourceGuru、Productive、Xebrio、Hive、Quire。在当今快节奏的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多企业在选择项目管理工具时常常面临困惑:...
项目管理系统   77  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用