Reputation: 21238
I have the following decorator, which saves a configuration file after a method decorated with @saveconfig
is called:
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:
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
. A first naive approach was to add a parameter to the decorator which holds the object, like @saveconfig(self)
, but this doesn't work.
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?
Upvotes: 8
Views: 2788
Reputation: 107608
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.
Upvotes: 0
Reputation:
You are passing object
as self
to the decorated method. 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). You can work around this, as pointed out by @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.self
!Upvotes: 4
Reputation: 601599
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.
Upvotes: 11