【问题标题】:Difference of returning a lambda function vs returning a method in python decorator返回 lambda 函数与在 python 装饰器中返回方法的区别
【发布时间】:2020-03-14 03:39:43
【问题描述】:

我试图了解在下面的装饰器中返回 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)

【问题讨论】:

    标签: lambda python-decorators


    【解决方案1】:

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

    使用return m.fm,属性O.fo绑定到m.fm产生的method对象,相当于M.fm.__get__(m, M)。重要的是,method 对象没有__get__ 方法,因此o.fo 直接为您提供M 类的方法。 现在参数 123 被分配,因此 1 被分配给 callingobj(2, 3) 被分配给 args

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

    【讨论】:

    • @chepener。而不是return m.fm。我尝试使用return m.fm.__func__ 并得到相同的结果。 m.fm.__func__ 确实有 __get__。我实际上试图弄清楚是否可以使用来自this thread 的堆栈多方法装饰器。使用 lambda 会破坏多个多方法装饰器的堆栈。
    猜你喜欢
    • 2020-12-04
    • 1970-01-01
    • 1970-01-01
    • 2020-04-28
    • 2021-01-17
    • 2020-02-10
    • 2019-11-05
    • 2016-10-20
    • 1970-01-01
    相关资源
    最近更新 更多