python - 装饰方法时访问绑定(bind)方法或自身

标签 python python-decorators python-descriptors

我有一个用例,我想用一种额外的调用方式来装饰一个方法,例如在这段代码中:

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 不是绑定(bind)方法而是函数,因此需要显式传递给 self

但是我该如何解决这个问题呢?从我对描述符的一点理解来看,它们只在查找类时相关,并且由于 func 不是类,所以 func.enhanced 没有被查找以一种我可以拦截的方式。

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

最佳答案

您可以返回一个 descriptor它返回一个对象,该对象使自身可调用并具有映射到您的 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

关于python - 装饰方法时访问绑定(bind)方法或自身,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52603071/

相关文章:

python - 在 Python 中将日期更改为友好格式

python - 使用 Python 在 MySQL 查询中使用 %s 进行字符串格式化时出错

python装饰器参数使用函数中的变量进行包装

python - 了解闭包在装饰器和函数包装器参数中的作用

python - PyWin32、Excel 和 "doing no damage"到现有系统

python - Pandas 替换为字符串和整数 - 不正确的行为?

python - 创建一个保存方法输入的装饰器 - 返回 'NoneType' 对象不可调用

python - 获取描述符对象的好方法

Python如何获取某些property.setter的绑定(bind)方法