[英]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: 其他说明:
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
上的所有内容都是实例属性。 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.