装饰器参数中无法识别的类

Posted

技术标签:

【中文标题】装饰器参数中无法识别的类【英文标题】:Class not recognized in decorator arguments 【发布时间】:2022-01-16 00:51:06 【问题描述】:

将类变量作为装饰器函数的参数传递会导致类名称为NameError。运行这个:

def log(prefix=None):

    def decorator(function):
        """Decorates the function"""

        def wrapper(*args, **params):
            """Wraps the function"""
            name = "-".join([prefix, function.__name__])

            result = function(*args, **params)
            print(f"completed the execution of 'name'")
            return result

        return wrapper

    return decorator
    
class ExampleClass:

    _CONSTANT = "test"

    def __init__(self, x):
        self._x = x

    @log(prefix=ExampleClass._CONSTANT)
    def product_of_number(self, y):
        return self._x * y

if __name__ == "__main__":
    x = ExampleClass(3)
    x.product_of_number(4)

导致错误

Traceback (most recent call last):
  File "/home/developer/reproduce_decorator_name_space.py", line 23, in <module>
    class ExampleClass:
  File "/home/developer/reproduce_decorator_name_space.py", line 31, in ExampleClass
    @log(prefix=ExampleClass._CONSTANT)
NameError: name 'ExampleClass' is not defined

但是,运行这个

def log(prefix=None):

    def decorator(function):
        """Decorates the function"""

        def wrapper(*args, **params):
            """Wraps the function"""
            name = "-".join([prefix, function.__name__])

            result = function(*args, **params)
            print(f"completed the execution of 'name'")
            return result

        return wrapper

    return decorator
    
_CONSTANT = "test"
class ExampleClass:

    def __init__(self, x):
        self._x = x

    @log(prefix=_CONSTANT)
    def product_of_number(self, y):
        return self._x * y

if __name__ == "__main__":
    x = ExampleClass(3)
    x.product_of_number(4)

给出输出

completed the execution of 'test-product_of_number'

为什么ExampleClass 无法识别?装饰的方法在__init__ 之后的类中并引用了self。错误消息本身是指模块ExampleClass。类名怎么不存在于命名空间中?

【问题讨论】:

这能回答你的问题吗? Python - Referencing class name from inside class body。 TL;DR,名称 ExampleClass 直到类块执行后才分配给。 你应该也可以在第一个sn-p中直接使用@log(prefix=_CONSTANT) 也相关***.com/q/19622550/11082165 【参考方案1】:

装饰器可以访问ExampleClass,可能不需要向装饰器传递参数:

def log(prefix=''):
    def decorator(function):
        """Decorates the function"""
        def wrapper(*args, **params):
            """Wraps the function"""
            # args[0] references the decorated class

            if prefix:
                # Option2: Prefix passed as string
                name = "-".join(
                    [getattr(args[0], prefix, ''), function.__name__])
            else:
                # Option1: No prefix
                name = "-".join([args[0]._CONSTANT, function.__name__])

            result = function(*args, **params)
            print(f"completed the execution of 'name'")
            return result

        return wrapper

    return decorator


class ExampleClass:

    _CONSTANT = "test"
    _ANOTHER_CONSTANT = "test2"

    def __init__(self, x):
        self._x = x

    @log()
    def product_of_number(self, y):
        return self._x * y

    @log('_ANOTHER_CONSTANT')
    def product_of_anothernumber(self, y):
        return self._x * y


if __name__ == "__main__":
    x = ExampleClass(3)
    x.product_of_number(4)
    x.product_of_anothernumber(4)

输出:

completed the execution of 'test-product_of_number'
completed the execution of 'test2-product_of_anothernumber'

【讨论】:

以上是关于装饰器参数中无法识别的类的主要内容,如果未能解决你的问题,请参考以下文章

Swift 3:将无法识别的选择器发送到手势识别器实例

尝试将参数传递给 void 时由无法识别的选择器导致的错误

错误:使用类引用时无法识别的选择器

目标动作模式的快速无法识别的选择器

NSInvalidArgumentException,使用 performSegueWithIdentifier 时发送到实例的无法识别的选择器

“无法识别的选择器”-将 AppDelegate 的 NSManagedObjectContext 导入其他类 (OSX) 时出错