【问题标题】:Decorating a class method with a class method用类方法装饰类方法
【发布时间】:2014-07-26 12:21:45
【问题描述】:

我正在用另一个类方法装饰一个类方法。类是这样的

from functools import wraps

class MyClass(object):
    def __init__(self):
        print('Within my class object')

    def my_decorator(func_to_decorate):
        @wraps(func_to_decorate)
        def wrapper(self):
            print('Before the call')

            func_to_decorate(self)

            print('After the function call')
        return wrapper

    @my_decorator
    def print_name(self):
        print('My name is ------ ')

mobj = MyClass()
mobj.print_name()

工作正常,我得到了我需要的输出

Before the call
My name is ------ 
After the function call

但是在查看装饰器my_decorator的函数定义时,我意识到该方法没有采用类方法通常作为其第一个参数self

我现在的问题是 - my_decorator 的类型是什么?是类方法、普通方法还是特殊方法?

通常,类中的方法采用隐式参数self,或者如果它的类方法采用隐式参数cls。装饰者不接受它们。

谁能解释一下这里发生了什么?

【问题讨论】:

  • 附带说明,您将类方法与实例方法混淆了。常规方法称为实例方法,因为它们将实例作为第一个参数self。类方法是使用装饰器 @classmethod 创建的,并将类作为它们的第一个参数,通常称为 cls
  • @SvenMarnach 我的错。感谢您纠正我。

标签: python decorator


【解决方案1】:

这是一个简单的函数,因为您不是从类或实例访问它,因此当在类定义中用作装饰器时,该函数不需要 selfcls。只有当我们使用类或实例访问它们时,这些函数才会强制使用隐式参数,因为通过类或实例访问它们会返回未绑定和绑定的方法,这些方法是原始函数的薄包装。

如果您将装饰器移到类之外,那么您会看到它希望您发送一个实例作为第一个参数:

MyClass.print_name = MyClass.my_decorator(MyClass.print_name)
mobj = MyClass()
mobj.print_name()

错误:

MyClass.print_name = MyClass.my_decorator(MyClass.print_name)
TypeError: unbound method my_decorator() must be called with MyClass instance as first argument (got instancemethod instance instead)

尽管您可以通过将 my_decorator 声明为既不期望 selfcls 的静态方法来防止此错误,也可以使用绑定的未绑定对象的 im_func 属性访问底层函数:

MyClass.print_name = MyClass.my_decorator.im_func(MyClass.print_name)

您应该阅读data model 页面上的可调用类型部分。

【讨论】:

    猜你喜欢
    • 2014-01-14
    • 2020-01-11
    • 1970-01-01
    • 2021-10-23
    • 2014-12-07
    • 2011-08-25
    • 2013-05-23
    • 1970-01-01
    • 2019-11-06
    相关资源
    最近更新 更多