i have a function with about 20-30 parameters
def function (a,b,c,d,e,....):
....
those paramenters may have any value, including "None".
I want to reasign a specifique string to each var that has the value "None" before my function does its magic.
But I dont want to have a huge block of code such as:
if a is None:
....
if b is None: ....
How can I go through each var and reasign its value if the condition is met?
ty
Unless you are doing something pretty exotic, this kind of thing is usually better handled by collecting the variables in a data structure, e.g. a dict like so:
def function(**kwargs):
default = 42
for key, val in kwargs.items():
if val is None:
kwargs[key] = default
...
print(kwargs)
# Example call
function(a=1, b=None)
You can assign to individual variables using the magic of exec, but it's generally not advised. Furthermore, it's not clear to me how one can successfully use this inside of a function as e.g. exec('a = 42') doesn't actually change the value of the local a variable.
If you have so many arguments to the function, then you can try using iterable unpacking operator * instead of explicitly defining each argument. In that you you will have more control over the contents of the arguments:-
def function(*args):
args = list(args)
for x, y in enumerate(args):
if y is None:
args[x] = "default_value"
print(args)
Then do a function call similar to :-
function(123, 3, None, "hello")
OUTPUT:-
[123, 3, 'default_value', 'hello']
I'm not recommending doing this, but if you insist:
def function(a,b,c,d,e,...):
myvars = locals() # Get a dictionary of parameters
arg_names = myvars.keys() # Get their names
for k in arg_names: # Replace the ones whose value is None
if myvars[k] == None:
myvars[k] = 'None'
Related
I have a function that returns a variable list of values and I know you can do this by using a tuple. To assign these variables you can then do something like a, b = func(..). However, if there is only one value returned you have to do a, = func(..) [notice the ,] rather than a = func(..). To achieve the latter you can include a test to see if there is one value to be returned or more (see example below) but I wonder if there is no easier or less verbose way to do this.
def foo(*args):
returnvalues = []
for arg in args:
arg += 100
returnvalues.append(arg)
if len(returnvalues) == 1:
return returnvalues[0]
else:
return tuple(returnvalues)
def baz(*args):
returnvalues = []
for arg in args:
arg += 100
returnvalues.append(arg)
return tuple(returnvalues)
a = foo(10)
b, c = foo(20, 30)
print(f'a={a}, b={b}, c={c}')
a, = baz(10)
b, c = baz(20, 30)
print(f'a={a}, b={b}, c={c}')
#
a=110, b=120, c=130
a=110, b=120, c=130
I believe you are referring to "tuple unpacking". Also known as destructive assignment. The word "tuple" is a bit of a misnomer as you can use any iterable / iterator. So returning a list is fine.
def f():
return [1]
(a,) = f()
b, = f()
You can also use list syntax on the left hand side. There's no difference to the byte code that is generated. It does make unpacking a single item look less like a syntax error in the case of b and slightly less verbose than a.
[c] = f()
I would avoid returning the value itself and not a list in the special case where only one argument is passed. The reason for this is it makes the code harder to be used in a generic manner. Any caller of the function needs to know how many arguments it's passing or check the return value (which is clumsy). For example:
result = f()
if isinstance(result, (list, tuple)):
smallest = min(result)
else:
smallest = result
# as opposed to this when you always return a list / tuple
smallest = min(f())
You can assign the returning value of such a function to a single variable, so that you can use it as a list or tuple:
a = baz(10, 20, 30)
print(', '.join(map(str, a))) # this outputs 110, 120, 130
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.
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]
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.
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'}
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
I realise that in the below functions f returns a tuple, and g returns a list.
def f():
return 1,2
def g():
return [1,2]
a,b=f()
c,d=g()
I have written a function which can handle any number of arguments.
def fun(*args):
return args
These arguments are entered like the f function above because they are the return value from a previous function.
output = fun(other_func())
When more that one value is return from fun the individual values can be retrieved by stating something like this...
output1, output2 = fun(other_func())
However, when one argument is used the output is something like below...
output = fun(other_func())
(1,)
Is there a way when there is only one value to have it return a single element instead of a tuple but still have the functionality of being able to return more than one value?
If you know the function is always going to return a one-element tuple, you can use a one-element tuple assignment:
output, = fun(other_func())
or simply index:
output = fun(other_func())[0]
But in this case, a simple Don't do that, don't return a tuple might also apply:
output = other_func()
As long as *args is a tuple, returning args will therefore return a tuple, even if there is only one parameter.
You should probably do something like:
def fun(*args):
if len(args) == 1:
args, = args
return args
This might be what you are looking for. With this method you must have at least one argument, but you will catch the other arguments in other if you have more.
def funct(*args):
return args
# end funct
if __name__ == '__main__':
foo, *other = funct(1, 2, 3, 4)
print(foo)
What is the correct way to specify an empty dict or list for a function?
def func_a(l=list(), d=dict()):
pass
def func_b(l=[], d={}):
pass
Either of those is fine if you're not going to mutate the input arguments...
However, if you're planning on mutating the list or the dict inside the function, you don't want to use either of the forms that you've supplied... You want to do something more like this:
def func(l=None, d=None):
if l is None:
l = list() #or l = []
if d is None:
d = dict() #or d = {}
Note that [] and {} will result in marginally faster execution. If this is in a really tight loop, I'd use that.
Neither. Default arguments in Python are evaluated once, at function definition. The correct way is to use None and check for it in the function:
def func(l=None):
if l is None:
l = []
...
See the discussion in this SO question.
I would like to do the following:
print "CC =",CC
but as a function so that i only have to write the variable CC once. I can't work out how to do this in a function as it always evaluates CC as a floating point number (which it is).... Is there a way to accept the input to a function as both a string and floating point number?
I tried this:
def printme(a):
b='%s' % a
print b
return b
but of course it only prints the value of a, not its name.
You could use the inspect module (see also this SO question):
def printme(x):
import inspect
f = inspect.currentframe()
val = f.f_back.f_locals[x]
print x, '=', val
CC = 234.234
printme('CC') # <- write variable name only once
# prints: CC = 234.234
Perhaps a dictionary is a better approach to the problem. Assuming you have several name-value pairs that you want to use, you can put them in a dict:
params = {"CC": 1.2345, "ID": "Yo!", "foo": "bar"}
Then, for example, you could print all the names and values nicely formatted like this:
for key in params:
print "{0} = {1}".format(key, params[key])
But since it is still unclear why you are trying to do this, it's hard to tell whether this is the right way.
I think this is your required solution:
def printme(x):
keys_list = [key for key, value in globals().iteritems() if value == x]
print keys_list
for key in keys_list:
if id(globals()[key]) == id(x):
result = "%s = %s" %(key, x)
print result
break
return result
for example if you declare a variable:
>>> c=55.6
then result of printme(c) will be
>>> 'c = 55.6'
Note: This solution is based on globally unique id matching.
Not exactly what you want, but easy to do:
def printme(**kwargs):
for key, value in kwargs.items():
print '%s=%s' % (key, value)
return value
In [13]: printme(CC=1.23, DD=2.22)
CC=1.23
DD=2.22
Out[13]: 1.23
If I understand you correctly you want something like this?
def f(a):
print('{0}: = {1}'.format(locals().keys()[0], a))
Update:
I am aware that the example doesn't make a lot of sense, as it's basically the same as:
def f(a):
print('a: {0}'.format(a))
I merely wanted to point the OP to locals() as I didn't quite understand what he's trying to accomplish.
I guess this is more what he's looking for:
def f(**kwargs):
for k in kwargs.keys():
print('{0}: {1}'.format(k, kwargs[k]))
f(a=1, b=2)
If I understand you correctly you want a shorthand for printing a variable name and its value in the current scope? This is in general impossible without using the interpreters trace function or sys._getframe, which should in general only be used if you know what you're doing. The reason for this is that the print function has no other way of getting the locals from the calling scope:
def a():
x = 1
magic_print("x") #will not work without accessing the current frame
What you CAN do without these is explicitly pass the locals to a function like this:
def printNameAndValue(varname, values):
print("%s=%s" % (varname, values[varname]))
def a():
x = 1
printNameAndValue("x", locals()) #prints 'x=1'
EDIT:
See the answer by catchemifyoutry for a solution using the inspect module (which internally uses sys._getframe). For completeness a solution using the trace function directly - useful if you're using python 2.0 and inspect isn't available ;)
from sys import settrace
__v = {} #global dictionary that holds the variables
def __trace(frame, event, arg):
""" a trace function saving the locals on every function call """
global __v
if not event == "call":
return __trace
__v.update(frame.f_back.f_locals)
def enableTrace(f):
""" a wrapper decorator setting and removing the trace """
def _f(*a, **kwa):
settrace(__trace)
try:
f(*a, **kwa)
finally:
settrace(None)
return _f
def printv(vname):
""" the function doing the printing """
global __v
print "%s=%s" % (vname, __v[vname])
Save it in a module and use like this:
from modulenamehere import enableTrace, printv
#enableTrace
def somefunction():
x = 1
[...]
printv("x")
used a global variable to achieve this,func.__globals__.keys() contains all the variables passed to func, so I filtered out the name startin with __ and stored them in a list.
with every call to func() the func.__globals__.keys() gets updated with the new variable name,so compare the new varn with the older glo results in the new variable that was just added.
glo=[]
def func(x):
global glo
varn=[x for x in func.__globals__.keys() if not x.startswith('__') and x!=func.__name__]
new=list(set(varn)^set(glo))
print("{0}={1}".format(new[0],x))
glo=varn[:]
output:
>>> a=10
>>> func(a)
a=10
>>> b=20
>>> func(20)
b=20
>>> foo='cat'
>>> func(foo)
foo=cat
>>> bar=1000
>>> func(bar)
bar=1000