为了账号安全,请及时绑定邮箱和手机立即绑定

如何通过`functools.wraps`从类装饰器访问装饰类的属性

如何通过`functools.wraps`从类装饰器访问装饰类的属性

呼唤远方 2022-05-19 14:31:42
我正在关注David Beazley 的 Python Cookbook的 Class Decorator recipe,这似乎更合适,因为它用于functools.wraps为装饰器提供更好的组织和属性。但是,我不太清楚如何(或是否)从装饰器本身访问实例的属性。这是代码片段:import timeimport typesfrom functools import wrapsclass TimeDecorator():    def __init__(self, func):        wraps(func)(self)    def __call__(self, *args, **kwargs):        tic = time.time()        func_return = self.__wrapped__(*args, **kwargs)        tac = time.time()        total_time = round((tac - tic) / 60, 2)        print(f'Operation Time: {total_time} min.')        # print(self.__wrapped__.test_attr) # going to give an error...        return func_return    def __get__(self, instance, cls):        if instance is None:            return self        else:            return types.MethodType(self, instance)class A():    def __init__(self):        self.test_attr = 0    @TimeDecorator    def do_something(self):        time.sleep(1) # example of stuff only...我试图__call__通过self.__wrapped__.test_attror访问装饰器的实例self.__wrapped__.__self__.test_attr,但它们都告诉我:AttributeError: 'function' object has no attribute 'test_attr'那么在这种情况下,我如何能够访问装饰类的属性呢?还是我必须使用另一种方式来构建我的装饰器?
查看完整描述

2 回答

?
慕田峪9158850

TA贡献1794条经验 获得超8个赞

您在实例方法上应用装饰器,因此此装饰方法绑定的实例将作为第一个参数传入,self您可以在其中找到您要查找的实例属性,因此您只需从参数中提取,在下面的示例中self命名wrapped_self:


def __call__(self, wrapped_self, *args, **kwargs):

    tic = time.time()

    func_return = self.__wrapped__(wrapped_self, *args, **kwargs)

    tac = time.time()

    total_time = round((tac - tic) / 60, 2)

    print(f'Operation Time: {total_time} min.')

    print(wrapped_self.test_attr)

    return func_return


查看完整回答
反对 回复 2022-05-19
?
慕尼黑8549860

TA贡献1818条经验 获得超11个赞

“self”是 do_something 函数的第一个参数。


所以你可以在你的装饰器中明确地识别它。 wrapped将是装饰类实例,*args并将包含所有其他位置参数。


from functools import wraps

import types

import time


class TimeDecorator():


    def __init__(self, func):

        wraps(func)(self)


    def __call__(self, wrapped, *args, **kwargs):

        tic = time.time()

        func_return = self.__wrapped__(wrapped, *args, **kwargs)

        tac = time.time()

        total_time = round((tac - tic) / 60, 2)

        print(f'Operation Time: {total_time} min.')

        print(wrapped.test_attr)

        return func_return


    def __get__(self, instance, cls):

        if instance is None:

            return self

        else:

            return types.MethodType(self, instance)



class A():


    def __init__(self):

        self.test_attr = 0


    @TimeDecorator

    def do_something(self):

        time.sleep(1) # example of stuff only...




a = A()

a.do_something()


查看完整回答
反对 回复 2022-05-19
  • 2 回答
  • 0 关注
  • 262 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号