首页 > 解决方案 > 装饰方法时访问绑定方法或自身

问题描述

我有一个用例,我想用另一种调用方法来装饰方法,例如在此代码中:

def decorator(func):
    def enhanced(*args, **kwargs):
        func(*args, **kwargs)

    func.enhanced = enhanced
    return func

@decorator
def function():
    pass

class X:
    @decorator
    def function(self):
        pass

x = X()

function()
function.enhanced()
x.function()
# x.function.enhanced()
x.function.enhanced(x)

前三个调用按预期工作,但x.function.enhanced()没有;我必须写信x.function.enhanced(x)才能让它发挥作用。我知道这是因为func传递给装饰器的不是绑定方法而是函数,因此需要self显式传递。

但我怎样才能解决这个问题?从我对描述符的了解来看,它们仅在查找类时才相关,并且由于func不是类,func.enhanced因此无法以我可以拦截的方式查找。

有什么我可以在这里做的吗?

标签: pythonpython-decoratorspython-descriptors

解决方案


您可以返回一个描述符,该描述符返回一个对象,该对象使自身可调用并且具有enhanced映射到您的enhanced包装函数的属性:

from functools import partial
def decorator(func):
    class EnhancedProperty:
        # this allows function.enhanced() to work
        def enhanced(self, *args, **kwargs):
            print('enhanced', end=' ') # this output is for the demo below only
            return func(*args, **kwargs)
        # this allows function() to work
        def __call__(self, *args, **kwargs):
            return func(*args, **kwargs)
        def __get__(self, obj, objtype):
            class Enhanced:
                # this allows x.function() to work
                __call__ = partial(func, obj)
                # this allows x.function.enhanced() to work
                enhanced = partial(self.enhanced, obj)
            return Enhanced()
    return EnhancedProperty()

以便:

@decorator
def function():
    print('function')

class X:
    @decorator
    def function(self):
        print('method of %s' % self.__class__.__name__)

x = X()

function()
function.enhanced()
x.function()
x.function.enhanced()

会输出:

function
enhanced function
method of X
enhanced method of X

推荐阅读