当我在 Python 类中装饰绑定(bind)方法时,我需要从外部类中获取此装饰器中的一些信息。那可能吗?

例如:

def modifier(func):
    import sys
    cls_namespace = sys._getframe(1).f_locals
    cls_namespace['data']  # dictonary has no key 'data'
    ...
    return func

class Parent:
    data = "Hi!"

class Child(Parent):

    @modifier
    def method(self):
        pass
cls_namespace 只是当前类的不完整命名空间,没有我需要获取的 data 字段。

有没有办法在装饰器中获取它?

最佳答案

函数修饰发生在执行类主体时,此时对类本身或其基类一无所知。这意味着 modifier 修饰了未绑定(bind)的函数对象,并且只有在实例上实际调用 func 时才会绑定(bind)它。

您可以返回一个包装函数来替换装饰函数,它将被绑定(bind),您将可以访问 self :

from functools import wraps

def modifier(func):
    @wraps(func)
    def wrapper(self, *args, **kwargs):
        # self is an instance of the class
        self.data
        return func(self, *args, **kwargs)
    return wrapper

每次在实例上调用 method 时,都会调用包装器。

如果必须在创建类时访问基类,则必须等到 class Child 语句完成执行。在 Python 3.6 之前,这只能通过类装饰器或元类实现;在创建类主体之后调用 each ,您将可以访问(至少)基类。

使用类装饰器,例如:
def modifier(cls):
    # cls is the newly created class object, including class attributes
    cls.data
    return cls

@modifier
class Child(Parent):
    def method(self):
        pass

现在注意装饰器的位置。

Python 3.6 添加了一个 __init_subclass__ method 也可以为您提供访问权限;每次创建当前类的子类时都会调用 (class) 方法:
class Parent:
    def __init_subclass__(cls, **kwargs):
        # cls is a subclass of Parent
        super().__init_subclass__(**kwargs)
        cls.data

    data = "Hi!"

class Child(Parent):
    def method(self):
        pass

关于python - 可以访问类及其祖先的绑定(bind)方法上的装饰器,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39698045/

10-15 17:41