简体   繁体   English

在decorator类中,访问包含装饰方法的类的实例

[英]Inside a decorator-class, access instance of the class which contains the decorated method

I have the following decorator, which saves a configuration file after a method decorated with @saveconfig is called: 我有以下装饰器,它在调用@saveconfig修饰的方法后保存配置文件:

class saveconfig(object):
    def __init__(self, f):
        self.f = f

    def __call__(self, *args):
        self.f(object, *args)
        # Here i want to access "cfg" defined in pbtools
        print "Saving configuration"

I'm using this decorator inside the following class. 我在下面的类中使用这个装饰器。 After the method createkvm is called, the configuration object self.cfg should be saved inside the decorator: 在调用createkvm方法之后,配置对象self.cfg应该保存在装饰器中:

class pbtools()
    def __init__(self):
        self.configfile = open("pbt.properties", 'r+')
        # This variable should be available inside my decorator
        self.cfg = ConfigObj(infile = self.configfile)

    @saveconfig
    def createkvm(self):
        print "creating kvm"

My problem is that i need to access the object variable self.cfg inside the decorator saveconfig . 我的问题是我需要访问对象变量self.cfg装饰内部saveconfig A first naive approach was to add a parameter to the decorator which holds the object, like @saveconfig(self) , but this doesn't work. 第一个天真的方法是向装饰器添加一个参数来保存对象,就像@saveconfig(self) ,但这不起作用。

How can I access object variables of the method host inside the decorator? 如何在装饰器中访问方法主机的对象变量? Do i have to define the decorator inside the same class to get access? 我是否必须在同一个类中定义装饰器才能获得访问权限?

You have to make your decorator class behave as a descriptor to be able to access the instance: 您必须使您的装饰器类表现为描述符才能访问该实例:

class saveconfig(object):
    def __init__(self, f):
        self.f = f

    def __get__(self, instance, owner):
        def wrapper(*args):
            print "Saving configuration"
            print instance.cfg
            return self.f(instance, *args)
        return wrapper

Your code passes object as first parameter to self.f() , where it should pass the pbtools instance. 您的代码将object作为第一个参数传递给self.f() ,它应该传递pbtools实例。

You are passing object as self to the decorated method. 您将object作为self传递给装饰方法。 The thing is, you can't easily get self because Python sees the decorated method, which is now an objects, and doesn't consider it a method (that should be passed self when called - or, more generally, that should work as a property returning a bound method). 问题是,你不能轻易获得self因为Python看到了装饰方法,它现在是一个对象,并且不认为它是一个方法(在调用时应该传递给self - 或者更常见的是,它应该像返回绑定方法的属性)。 You can work around this, as pointed out by @Sven Marnach. 正如@Sven Marnach所指出的,你可以解决这个问题。

However, you could easily rewrite this decorator without a class, using a closure (is a bit shorter and also solves the above problem): 但是,您可以使用闭包轻松地重写此装饰器而不使用类(稍微缩短并解决上述问题):

def saveconfig(f):
    @functools.wraps(f) # to preserve name, docstring, etc.
    def wrapper(*args, **kwargs): # **kwargs for compability with functions that use them
        f(*args, **kwargs)
        # save config
    return wrapper

Other notes: 其他说明:

  • Terminology mixup: There is no class variable in the example. 术语混淆:示例中没有类变量。 A class variable would be x = ... indented as far as the method definitions and be shared between all instances (specifically, it would be an attribute of the object that is pbtools ) - everything on self is an instance attribute. 类变量将是x = ...缩进到方法定义并在所有实例之间共享(具体地说,它将是对象的属性pbtools ) - self上的所有内容都是实例属性。
  • At class definition time (when you define methods, apply decorators, etc.) there is no self ! 在类定义时(当您定义方法,应用装饰器等)时,没有self

You can also use a simple function for what you want: 您还可以根据需要使用简单的函数:

def saveconfig(f):
    # this method replaces the decorated, so `self` will be the pbtools instance
    def wrapped(self, *args):
        f(self, *args)
        # Here i want to access "cfg" defined in pbtools
        print "Saving configuration", self.cfg
    return wrapped

If saveconfig must be a class then you need Sven's solution. 如果saveconfig必须是一个类,那么你需要Sven的解决方案。

暂无
暂无

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

相关问题 Python:如何从类装饰器中访问装饰类的实例? - Python: How do I access an decorated class's instance from inside a class decorator? 如何在类中声明装饰器,以装饰已经装饰的继承方法? - How to declare decorator inside a class, to decorate an already decorated, inherited method? 从装饰器访问拥有装饰方法的类 - Accessing the class that owns a decorated method from the decorator 将参数传递给装饰器的类方法将被装饰 - Pass parameters to a decorator for a class method is to be decorated 实例方法的装饰器可以访问类吗? - Can a decorator of an instance method access the class? 如何在使用 `functools.wraps` 并保留对装饰实例的访问权时创建一个带参数的装饰器类 - How to Create a Decorator Class that takes Arguments while Using `functools.wraps` and Preserving Access to the Decorated Instance 如何告诉 mypy class 装饰器向装饰类添加了一个方法 - How to tell mypy that a class decorator adds a method to the decorated-class 如何在 DRF 的 urls.py 文件中访问从 APIView Class 继承的视图的 @action 装饰器装饰的方法? - How to Access method decorated with @action decorator of a view inherited from APIView Class in urls.py file in DRF? Python,参考 class 实例/方法在装饰 function - Python, reference class instance/method in decorated function 类中的装饰器:无法在装饰函数内部使用self - Decorator in class: cannot use self inside the decorated function
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM