Reputation: 14292
template.render(current_user=current_user, thread=thread, messages=messages)
Is there a dont-repeat-yourself compliant way to do whatever=whatever
? Like a magic symbol to prepend the variable name with or something like this ~whatever, ~something, ~etc
?
Upvotes: 0
Views: 173
Reputation: 123473
Here's a decorator, inspired to some degree by the one in a recipe titled Keyword Argument Injection with Python Decorators, that might help. It certainly cuts down on the repetition, maybe too much.
import sys
def injectlocalargs(inFunction):
def outFunction(*args, **kwargs):
# get decorated function's argument names
func_argnames = inFunction.func_code.co_varnames
# caller's local namespace
namespace = sys._getframe(1).f_locals
# add values of any arguments named in caller's namespace
kwargs.update([(name,namespace[name]) for name in func_argnames if name in namespace])
# call decorated function and return its result
return inFunction(*args, **kwargs)
return outFunction
##### testbed #####
class template_class:
@injectlocalargs
def render(self, extra_stuff, current_user, thread, messages):
print 'render() args'
print ' extra_stuff:%s, current_user:%s, thread:%s, messages:%s' % (extra_stuff, current_user, thread, messages)
def test():
current_user = 'joe'
thread = 42
messages = ['greetings',"how's it going?"]
template = template_class()
template.render('extra_stuff')
test()
Output:
render() args
extra_stuff:extra_stuff, current_user:joe, thread:42, messages:['greetings', "how's it going?"]
Upvotes: 0
Reputation: 375604
If your template.render()
method accepts any keyword arguments, and you don't mind passing it extra arguments that it won't use, then use:
template.render(**locals())
This will pass every local variable in under its own name.
Keep in mind that many people will object to the sloppiness implicit in this solution.
Upvotes: 1
Reputation: 156178
I sort of like aaronasterling's idea, but obviously it's not quite short. suppose you have a naming convention for local variables. variables that will be passed to the call have one naming style and everything else follows a different convention. For instance, suppose you just say that the leading character of 'private' locals begin with an underscore. thus:
def localargs (kwargs):
return dict((k, v) for (k, v) in kwargs.iteritems() if k[0] != '_')
def somefunction(public_arg, _private_arg):
public_local = "foo"
_private_local = "bar"
...
template.render(**localargs(locals()))
but that's hideous, don't do that.
Upvotes: 0
Reputation: 70148
You can pass keyword arguments from a dictionary if you want.
def a(b, c, d):
pass
someArgs = {"b" : 1, "c" : 2, "d" : 3}
a(**someArgs)
If you want to prepend something to the variable names, you can change the dictionary keys:
a(**dict(("prefix_" + k, v) for k, v in someArgs.items()))
And as an aside, you know that you can't specify arguments called "~arg" in your source code?!
Upvotes: 0
Reputation: 816472
No, there is not.
For what it's worth, you can create a dictionary with your parameters and pass it with:
template.render(**parameters)
Note: You should always favor readability!
Upvotes: 4