In most of the object oriented codes we write, we need to set class attributes to the given argument values and this is a very line-consuming thing. To get over these redundant lines, I found a solution using decorators.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | class RedundantTest:
def __init__(self, x, y, z, t):
# Here are the redundant lines:
self.x = x
self.y = y
self.z = z
self.t = t
print x,y,z,t
# ===================================
def injectArguments(inFunction):
def outFunction(*args,**kwargs):
_self = args[0]
_self.__dict__.update(kwargs)
inFunction(*args,**kwargs)
return outFunction
class Test:
@injectArguments
def __init__(self, x, y, z, t):
# We don't have to set each attribute. They're already set by injectArguments
print self.x,self.y,self.z,self.t
@injectArguments
def function(self, name):
print "Name:",self.name
t = Test(x=4, y=5, z=6, t=7)
t.function(name="Emre")
|
args dictionary contains the arguments and kwargs dictionary contains the keyword arguments. arg[0] corresponds to self argument. So what we do is we update self.__dict__ with {'x':4, 'y':5,'z':6,'t':7} where self corresponds to the Test instance. This way, bulky self.x = x, etc. codes are eliminated.
I should note that keyword arguments (x=4, y=5, ... ) should be used to use this decorator.
I don't know if any built-it decorator like this exists in Python libraries but it seems like I'll be using this a lot.
This solution is a variant that allow to pass parameter not only with kwargs notation.
Wow! That's what I've been looking for. It's been really useful to learn func_code.co_varnames. Thank you very much. This way, this snippet has became really useful.
In Python 2.4+ the code snippet below from @Filippo Squillace's version:
could be replaced with simply:
Regardless, both the original and modified recipe's seem elegant and useful.
Both the OP's and Filippo Squillace's variant should end their nested
outFunction
defintion by returning the result of calling the method being decorated, otherwise it will default toNone
. In other words, like this:Adapted for python3:
```py
!/usr/bin/env python3
def injectArguments(inFunction): """ Decorator injecting arguments of a method as attributes
if __name__=='__main__': class Test: @injectArguments def __init__(self, name, surname): pass
```
Thank you!
Adapted for python3:
Thank you!
Modified to accept default values of non-passed arguments:
You can find a new debugged version here: https://gist.github.com/Zzortell/2403054294b6312a32033b747ec0ad2c