Reputation: 3802
I have a python function that receives many arguements. I want to change all the functions arguements to lowercase. I have this code:
functionOne(para, paraa, parab):
arguments = locals()
print arguments
for keys in arguments:
arguments[keys] = str(arguments[keys]).lower()
print arguments[keys]
print para
With the output:
{'para':'HP', 'paraa':'MA', 'parab':'aM'}
hp
ma
am
HP
I would like para to equal hp not HP.
Upvotes: 0
Views: 11591
Reputation: 1718
Modifying the return dictionary of locals() is undefined behavior. It won't do what you want. May I suggest using a decorator instead:
from functools import wraps
def lower_args(f):
@wraps(f)
def wrapper(*args, **kwargs):
args = list(args)
for i, a in enumerate(args):
if isinstance(a, basestring):
args[i] = a.lower()
for key, val in kwargs.items():
if isinstance(val, basestring):
kwargs[key] = val.lower()
return f(*args, **kwargs)
return wrapper
@lower_args
def functionOne(para, paraa, parab):
print para
Upvotes: 0
Reputation: 309929
This isn't possible. Python's locals
don't modify the names in the function's namespace. According to the docs:
Note The contents of this dictionary should not be modified; changes may1 not affect the values of local and free variables used by the interpreter.
The only solution is to keep using arguments
to access the values, or to lowercase each one by hand, or to pass an iterable of arguments rather than explicitly naming each one.
1"may" is probably in there because implementations that aren't Cpython are free to implement locals
differently. A better wording might be "changes are not required to affect ..."
At a higher level, having a function with enough arguments that lowercasing "by hand" is cumbersome is a bit of a "code-smell" and might mean that a refactor is in order.
Upvotes: 2
Reputation: 49318
There's no need to mess with locals()
. If your function just has positional parameters, it shouldn't have too many, so you can change them one by one.
functionOne(para, paraa, parab):
arguments = (para, paraa, parab)
print arguments
para, paraa, parab = map(str.lower, arguments)
print para
If your function will have a larger, arbitrary number of arguments, use *
:
functionOne(*args):
print args
args = tuple(map(str.lower, args))
print args[0]
Upvotes: 3
Reputation: 77847
para = para.lower()
paraa = paraa.lower()
parab = parab.lower()
The loop you wrote works on a constructed list, not the original arguments. here's the full change:
def functionOne(para, paraa, parab):
arguments = locals()
print arguments
for keys in arguments:
arguments[keys] = str(arguments[keys]).lower()
print arguments[keys]
para = para.lower()
paraa = paraa.lower()
parab = parab.lower()
print locals()
functionOne('HP', 'MA', 'aM')
Giving output:
{'parab': 'aM', 'paraa': 'MA', 'para': 'HP'}
am
ma
hp
{'keys': 'para', 'parab': 'am', 'paraa': 'ma', 'arguments': {...}, 'para': 'hp'}
Upvotes: 0