I'm new to python and I'm trying to figure out if I can pass named keywords by string without calling them explicitly.
Here an example:
def test(height, weight):
print("h=" + str(height))
print("w=" + str(weight))
test(weight=1, height=2) # output
a = "weight"
b = "height"
test(a=1, b=2) # same output
Is this possibile?
Thanks!
Use a dict.
kwargs = {a: 1, b: 2}
test(**kwargs)
Sort of. Try this:
a = "weight"
b = "height"
kwargs = {
a: 1,
b: 2
}
test(**kwargs)
I think the other answers are missing the point. Sure, they are correct answer to the problem you're suggesting, but they're not the answer you're looking for.
I'll condense your code a little to this:
def test(a):
print(a)
test("hello, world!") # Works!. The string is passed to the first paramater, which
# is 'a'.
test(a = "hello, world!") # Works! The 'a' parameter that the function accepts is
# set to "hello, world".
test(b = "hello, world!") # Fails. 'b' does not exist as a parameter in test().
b = "a" # You're trying to set the 'b' keyword to equal the 'a' keyword here.
# This does NOT work, which we'll see in a bit.
test(b = "Hello, world!") # Still fails. The function checks whether 'b' exists
# as a parameter. There is no such parameter.
print(b) # Prints "a". The variable 'b' was NOT changed when test() was called.
# You merely tried to change the parameter 'b' of the function test(),
# which did not exist in the first place.
Related
This question already has answers here:
What is the purpose of the return statement? How is it different from printing?
(15 answers)
Closed 8 months ago.
In my previous question, Andrew Jaffe writes:
In addition to all of the other hints and tips, I think you're missing something crucial: your functions actually need to return something.
When you create autoparts() or splittext(), the idea is that this will be a function that you can call, and it can (and should) give something back.
Once you figure out the output that you want your function to have, you need to put it in a return statement.
def autoparts():
parts_dict = {}
list_of_parts = open('list_of_parts.txt', 'r')
for line in list_of_parts:
k, v = line.split()
parts_dict[k] = v
print(parts_dict)
>>> autoparts()
{'part A': 1, 'part B': 2, ...}
This function creates a dictionary, but it does not return something. However, since I added the print, the output of the function is shown when I run the function. What is the difference between returning something and printing it?
print simply prints out the structure to your output device (normally the console). Nothing more. To return it from your function, you would do:
def autoparts():
parts_dict = {}
list_of_parts = open('list_of_parts.txt', 'r')
for line in list_of_parts:
k, v = line.split()
parts_dict[k] = v
return parts_dict
Why return? Well if you don't, that dictionary dies (gets garbage collected) and is no longer accessible as soon as this function call ends. If you return the value, you can do other stuff with it. Such as:
my_auto_parts = autoparts()
print(my_auto_parts['engine'])
See what happened? autoparts() was called and it returned the parts_dict and we stored it into the my_auto_parts variable. Now we can use this variable to access the dictionary object and it continues to live even though the function call is over. We then printed out the object in the dictionary with the key 'engine'.
For a good tutorial, check out dive into python. It's free and very easy to follow.
The print statement will output an object to the user. A return statement will allow assigning the dictionary to a variable once the function is finished.
>>> def foo():
... print "Hello, world!"
...
>>> a = foo()
Hello, world!
>>> a
>>> def foo():
... return "Hello, world!"
...
>>> a = foo()
>>> a
'Hello, world!'
Or in the context of returning a dictionary:
>>> def foo():
... print {'a' : 1, 'b' : 2}
...
>>> a = foo()
{'a': 1, 'b': 2}
>>> a
>>> def foo():
... return {'a' : 1, 'b' : 2}
...
>>> a = foo()
>>> a
{'a': 1, 'b': 2}
(The statements where nothing is printed out after a line is executed means the last statement returned None)
I think you're confused because you're running from the REPL, which automatically prints out the value returned when you call a function. In that case, you do get identical output whether you have a function that creates a value, prints it, and throws it away, or you have a function that creates a value and returns it, letting the REPL print it.
However, these are very much not the same thing, as you will realize when you call autoparts with another function that wants to do something with the value that autoparts creates.
you just add a return statement...
def autoparts():
parts_dict={}
list_of_parts = open('list_of_parts.txt', 'r')
for line in list_of_parts:
k, v = line.split()
parts_dict[k] = v
return parts_dict
printing out only prints out to the standard output (screen) of the application. You can also return multiple things by separating them with commas:
return parts_dict, list_of_parts
to use it:
test_dict = {}
test_dict = autoparts()
Major difference:
Calling print will immediately make your program write out text for you to see. Use print when you want to show a value to a human.
return is a keyword. When a return statement is reached, Python will stop the execution of the current function, sending a value out to where the function was called. Use return when you want to send a value from one point in your code to another.
Using return changes the flow of the program. Using print does not.
A function is, at a basic level, a block of code that can executed, not when written, but when called. So let's say I have the following piece of code, which is a simple multiplication function:
def multiply(x,y):
return x * y
So if I called the function with multiply(2,3), it would return the value 6. If I modified the function so it looks like this:
def multiply(x,y):
print(x*y)
return x*y
...then the output is as you would expect, the number 6 printed. However, the difference between these two statements is that print merely shows something on the console, but return "gives something back" to whatever called it, which is often a variable. The variable is then assigned the value of the return statement in the function that it called. Here is an example in the python shell:
>>> def multiply(x,y):
return x*y
>>> multiply(2,3) #no variable assignment
6
>>> answer = multiply(2,3) #answer = whatever the function returns
>>> answer
6
So now the function has returned the result of calling the function to the place where it was called from, which is a variable called 'answer' in this case.
This does much more than simply printing the result, because you can then access it again. Here is an example of the function using return statements:
>>> x = int(input("Enter a number: "))
Enter a number: 5
>>> y = int(input("Enter another number: "))
Enter another number: 6
>>> answer = multiply(x,y)
>>> print("Your answer is {}".format(answer)
Your answer is 30
So it basically stores the result of calling a function in a variable.
def add(x, y):
return x+y
That way it can then become a variable.
sum = add(3, 5)
print(sum)
But if the 'add' function print the output 'sum' would then be None as action would have already taken place after it being assigned.
Unfortunately, there is a character limit so this will be in many parts. First thing to note is that return and print are statements, not functions, but that is just semantics.
I’ll start with a basic explanation. print just shows the human user a string representing what is going on inside the computer. The computer cannot make use of that printing. return is how a function gives back a value. This value is often unseen by the human user, but it can be used by the computer in further functions.
On a more expansive note, print will not in any way affect a function. It is simply there for the human user’s benefit. It is very useful for understanding how a program works and can be used in debugging to check various values in a program without interrupting the program.
return is the main way that a function returns a value. All functions will return a value, and if there is no return statement (or yield but don’t worry about that yet), it will return None. The value that is returned by a function can then be further used as an argument passed to another function, stored as a variable, or just printed for the benefit of the human user.
Consider these two programs:
def function_that_prints():
print "I printed"
def function_that_returns():
return "I returned"
f1 = function_that_prints()
f2 = function_that_returns()
print "Now let us see what the values of f1 and f2 are"
print f1 --->None
print f2---->"I returned"
When function_that_prints ran, it automatically printed to the console "I printed". However, the value stored in f1 is None because that function had no return statement.
When function_that_returns ran, it did not print anything to the console. However, it did return a value, and that value was stored in f2. When we printed f2 at the end of the code, we saw "I returned"
The below examples might help understand:
def add_nums1(x,y):
print(x+y)
def add_nums2(x,y):
return x+y
#----Function output is usable for further processing
add_nums2(10,20)/2
15.0
#----Function output can't be used further (gives TypeError)
add_nums1(10,20)/2
30
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-124-e11302d7195e> in <module>
----> 1 add_nums1(10,20)/2
TypeError: unsupported operand type(s) for /: 'NoneType' and 'int'
I need to change the global variable S at a.py from b.py, but it is used as a default value in a function at a.py.
a.py
S = "string"
def f(s=S):
print(s)
print(S)
b.py
import a
def main():
a.S = "another string"
a.f()
if __name__ == "__main__":
main()
python b.py outputs
string
another string
instead of expected
another string
another string
If I call a.f in b.py like this
a.f(a.S)
this works as expected, but is there any way to change default variable value?
The short answer is: You can't.
The reason for this is that the function default arguments are created at function definition time, and the defaults are not meant to be re-defined. The variable name is bound once to a value and that is all, you can't re-bind that name to another value. First, let's look at variables in global scope:
# create a string in global scope
a = "string"
# b is "string"
b = a
a += " new" # b is still "string", a is a new object since strings are immutable
You've now just bound a new name to "string", and "string new" is a completely new value bound to a, it does not change b because str += str returns a new str, making a and b refer to different objects.
The same happens with functions:
x = "123"
# this expression is compiled here at definition time
def a(f=x):
print(f)
x = "222"
a()
# 123
The variable f was defined with the default of "123" at definition time. This can't be changed. Even with mutable defaults such as in this question:
x = []
def a(f=x):
print(x)
a()
[]
# mutate the reference to the default defined in the function
x.append(1)
a()
[1]
x
[1]
The default argument was already defined, and the name f was bound to the value [], that cannot be changed. You can mutate the value associated with f, but you cannot bind f to a new value as a default. To further illustrate:
x = []
def a(f=x):
f.append(1)
print(f)
a()
x
[1]
# re-defining x simply binds a new value to the name x
x = [1,2,3]
# the default is still the same value that it was when you defined the
# function, albeit, a mutable one
a()
[1, 1]
It might be better to either A) pass the global variable in as an argument to the function or B) use the global variable as global. If you are going to change the global variable you wish to use, don't set it as a default parameter and choose a more suitable default:
# some global value
x = "some default"
# I'm choosing a default of None here
# so I can either explicitly pass something or
# check against the None singleton
def a(f=None):
f = f if f is not None else x
print(f)
a()
some default
x = "other default"
a()
other default
a('non default')
non default
I'm looking to strip the white-space from each of the arguments in a function that takes a bunch of required strings. And I don't want to use **kwargs which defeats the purpose of the required arguments.
def func(a, b, c):
for argument, argument_value in sorted(list(locals().items())):
print(argument, ':', argument_value)
argument_value = ' '.join(argument_value.split())
print(argument, ':', argument_value)
print('a is now:', a)
func(a=' a test 1 ', b=' b test 2 ', c='c test 3')
Output
a : a test 1
a : a test 1
b : b test 2
b : b test 2
c : c test 3
c : c test 3
a is now: a test 1
Desired output for the original 'a' argument:
a is now : a test 1
Being a newb, I cobbled this together and then read the python documentation which clearly states.
locals()
Update and return a dictionary representing the current local symbol table. Free variables are returned by locals() when it is
called in function blocks, but not in class blocks.
Note
The contents of this dictionary should not be modified; changes may not affect the values of local and free variables used by the
interpreter.
What is the right way to do what I'm attempting here?
You can use a decorator to do that kind of task.
The idea is to mask the real function behind a decorator that will take generic arguments, do modifications "on them" (actually create new variables containing the modifications) and pass the modified arguments to the real function.
def strip_blanks(f):
def decorated_func(*args, **kwargs):
# Strip blanks from non-keyword arguments
new_args = [ " ".join(arg.split()) for arg in args]
# Strip blanks from keyword arguments
new_kwargs = { key:" ".join(arg.split()) for key,arg in kwargs.items()}
# Pass the modified arguments to the decorated function
# And forward its result in case needed
return f(*new_args, **new_kwargs)
return decorated_func
#strip_blanks
def func(a, b, c):
for i in a, b, c:
print(i)
Then you'd get
>>> func(a = " foo bar", b = "baz boz", c = "biz buz ")
foo bar
baz boz
biz buz
>>> func(" foo bar", "baz boz", "biz buz ")
foo bar
baz boz
biz buz
>>> func(a = " foo bar", b = "baz boz", c = "biz buz ", d = " ha ha")
Traceback (most recent call last):
File "<pyshell#40>", line 1, in <module>
func(a = " foo bar", b = "baz boz", c = "biz buz ", d = " ha ha")
File "<pyshell#35>", line 5, in decorated_func
f(*new_args, **new_kwargs)
TypeError: func() got an unexpected keyword argument 'd'
>>>
I would start by changing your definition to def func(**kwargs). This takes whatever keyword arguments you provide and adds them to a dictionary. For example:
def func(**kwargs):
for key in kwargs:
print key, kwargs[key]
>>> func(a='hello', b='goodbye')
a hello
b goodbye
>>> func()
>>>
As you can see, it works with no arguments as well (nothing to print). From there, have a look at the string method strip.
EDIT:
You're giving some pretty arbitrary restrictions. So, what you want is:
...a specific number of arguments with specific names.
...to loop over the arguments.
...perform some work on each one.
The fastest way to do what you want is with locals() I think. I'm guessing what you're balking at is the bit about the contents of the dictionary not being modified. This isn't a concern here, as you're looping over a list of tuples representing the keys and values from the locals dictionary. When you do for argument, argument_value in ____ you are unpacking the tuples and assigning one value to each of those names. When you then do argument_value = 'blahblah' you are assigning a new string to argument_value. Strings are immutable, so you can't change the value "in placed". You aren't changing the value in the dictionary, as you haven't assigned anything to the dictionary's key.
When I run the following program it prints "2" and then "1" when i want it to print "2" and then "2". What have i done wrong?
def thingy(a):
a= a + 1
print(a)
return a
a=1
thingy(a)
print(a)
Many thanks if you can help.
You haven't re-assigned the a variable in your global scope. The a variable in the global scope isn't the same as in the function. To be more clear, look at this:
def thingy(arg):
arg = arg + 1
print(arg)
return arg
a=1 # Assign a to 1
thingy(a) # Do some work without altering variable
print(a) # Print a, which is 1...
a = thingy(a) # Here, a will be equals to two now.
With global option
You can also edit the global scope by adding global a at the beginning of the function and don't pass any argument to the function:
def thingy():
global a
a= a + 1
print(a)
return a
a=1
thingy()
print(a)
But prefer the first method, more cleaner.
You have remember that variables in functions are only in scope inside the function. So when you create this function:
def thingy(a):
a= a + 1
print(a)
return a
a is only in scope inside the function. No changes made to it exist outside the function. To use the returned value of a function you need to set a variable to be equal to the result of the function. So the a in the function and the a outside the function are not the same variable. Example:
def foo(a):
a = 2
return a
a = 1 #set a = 1
foo(a) #use a in function
a will still be one since the a inside the function is now out of scope.
a = 1
a = thingy(a)
print(a)
although it may look like you're setting a to 2 in the method, the scope is completely different. Imagine if you'd named the variable in the method b instead. They're different variables with the same name because of the scope.
Being a number your 'a' variable that you pass to thingy function is immutable and thus all manipulations inside your functions will not be passed back to original a. Though if you pass a as a list and change it in the function then you'll see all the changes you've made to the list after returning from a function.
def thingy(a):
a[0]= a[0] + 1
print(a[0])
a=[0]
thingy(a)
print(a[0])
you are mistaken with the a's.
functions live in their own world. they use vars of themselves. unless you tell them to use a global var.
you have lots of options to fix this:
use "global" to tell the function to use the global a.
def thingy(a):
global a;
a= a + 1
print(a)
return a
just by adding the line "global a" you tell the function "hey, you are not alone - use everyone's a".
the problem is that in your script, you use a as a global variable, and as the argument the function take. instead, write:
def thingy():
because you don't need the argument anymore.
so your code will look like this:
def thingy():
global a;
a= a + 1
print(a) #You don't need the "return a", you don't use it.
a=1
thingy()
print(a)
Use the return.
instead of using a global var, you can set "a" to whatever the function returns.
so instead of just calling thingy(a), use:
a = thingy(a)
I will use variable called "b" inside the function.
def thingy(b):
b = b + 1
print(b)
return b
a = 1
a = thingy(a)
print(a)
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