首页 > 解决方案 > 返回 lambda 函数与在 python 装饰器中返回方法的区别

问题描述

我试图了解在下面的装饰器中返回 lambda 与方法的区别。返回 m.fm 时,调用对象实例“o”丢失且未由装饰器传递。装饰器将在返回 lambda 函数时传递实例。是否可以通过在装饰器中返回方法来传递调用对象?

def deco(*type):
    def wrapper(func):
        m = M()
        # return lambda callingobj, *args: m.fm(callingobj, *args)
        return m.fm
    return wrapper

class M(object):
    def fm(self, callingobj, *args):
        print(f'self_ {callingobj}, args {args}')

class O(object):
    @deco('int')
    def fo(self, *args):
        print(f'{args}')


o = O()
o.fo(1, 2, 3)

输出:

  1. return lambda callingobj, *args: m.fm(callingobj, *args)

    callingobj <__main__.O object at 0x000002453BE95760>, args (1, 2, 3)

  2. return m.fm

    callingobj 1, args (2, 3)

标签: lambdapython-decorators

解决方案


使用 lambda 表达式,属性O.fo绑定到一个function对象。访问时,o.fo产生 的值O.fo.__get__(o, O),这是一个method将其参数传递给函数的对象。也就是说,__get__返回一个函数,其第一个参数是callingobj,它被绑定到o。其余参数绑定为元组(1, 2, 3) toargs`

使用return m.fm,属性O.fo绑定到由method产生的对象m.fm,相当于M.fm.__get__(m, M)。重要的是,一个method对象没有__get__方法,所以直接o.fo给你M类的方法。现在,参数1,23被分配,使得 1 被分配给callingobj并且(2, 3)被分配给args

换句话说,区别在于某些函数的__get__方法相对于o.fo处理参数的顺序。


推荐阅读