简体   繁体   English

Python从装饰器返回额外的值

[英]Python return extra value from decorator

I have some functions and I want to do some computation based on the argument values passed to it in a decorator. 我有一些函数,我想根据装饰器中传递给它的参数值进行一些计算。 I am able to achieve this but the decorator populates an important object which I would like to reuse later on. 我能够实现这一点,但装饰器会填充一个重要的对象,稍后我将重用该对象。 eg.. 例如..

def my_awesome_decorator(*d):
    how_do_i_return_this_object_which_got_created_here
    def wrapping_function(func):
        def wrapper(*args, **kwargs):
            ...
        return wrapper
    return wrapping_function


class A:
    @my_awesome_decorator(d)
    def fun(a, b, c):
        ...

I want the object to be easily accessible using object_A.how_do_i_return_this_object_which_got_created_here 我希望使用object_A.how_do_i_return_this_object_which_got_created_here可以轻松访问该对象

This is not something a decorator can do. 这不是装饰员可以做的。 All that a decorator can do is return something different for the given function object. 装饰者所能做的就是为给定的函数对象返回不同的东西。 You don't have a choice what the return value is assigned to, in the namespace. 在命名空间中,您无法选择将返回值分配给什么。

Better options are: 更好的选择是:

  • using an attribute on the decorated function: 在修饰函数上使用属性:

     def my_awesome_decorator(*d): def wrapping_function(func): def wrapper(*args, **kwargs): # ... wrapper.some_attribute = ... return wrapper return wrapping_function 

    after which ClassObject.methodname.some_attribute and instance.methodname.some_attribute are available. 之后可以使用ClassObject.methodname.some_attributeinstance.methodname.some_attribute

  • For Python 3.6 or newer, you can add a __init_subclass__ method to a baseclass for your classes. 对于Python 3.6或更高版本,可以为类的基类添加__init_subclass__方法。 It could combine with an attribute set by your decorator to copy an attribute over to the class: 它可以与装饰器设置的属性结合使用,以将属性复制到类中:

     class BaseClass: def __init_subclass__(cls, **kwargs): super().__init_subclass__() special = None for attr in vars(cls).values(): special = getattr(attr, '_special_attribute_name', None) if special is not None: break cls.target_attribute = special 

    after which subclasses will copy across the first method._special_attribute_name attribute that is found to the class object; 之后,子类将跨找到的第一个method._special_attribute_name属性复制到类对象; a decorator can set that attribute on a method. 装饰者可以在方法上设置该属性。

  • For earlier Python versions, use a metaclass to do the same: 对于早期的Python版本,请使用元类执行相同的操作:

     class SomeMetaClass(type): def __new__(mcls, name, bases, namespace, **kwds): special = None for attr in namespace.values(): special = getattr(attr, '_special_attribute_name', None) if special is not None: break namespace['target_attribute'] = special return super().__new__(mcls, name, bases, namespace, **kwds) 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM