Passing Variables Simplified - python

I am working on a project, but I need to pass variables between functions and I do not know how. I am not very good at python at all. I just started learning it like a month ago. Anyhow I just want to know the simplest way to pass a variable between functions.
Can I just do this?
def a():
variable1 = 0
answer = raw_input()
if answer == "a":
print "Correct"
b()
def b():
#Variable1 should now be here also right?
a()

Add a parameter to your function b.
def b(argument1):
print 'This is function b(), argument1=', argument1
def a():
# call func b, passing it 42 as an argument
b(42)
Python Functions
In Python you can use global variables, but this is not the recommended way of doing things. Global variables should generally be avoided.
def b()
print 'This is function b(), globalVar1=', globalVar1
def a()
global globalVar1
globalVar1 = 88
b()
Using global variables in a function other than the one that created them

The easiest way to pass a variable between functions is to define the necessary function to accept an argument. Check out functions -part in the official tutorial
In your case you want to pass variable1 to b. Define b as such:
def b(var):
print var
# Whatever else you want to do..
def a():
variable1 = 0
answer = raw_input()
if answer == "a":
print "Correct"
b(variable1)
Your original code does not work because variables inside functions are local to those functions. Using function arguments is the correct way of doing what you want.

Related

Is there a way to use variable from outer function in the inner function body, in Python?

The pattern of the code that I try to build is:
def OuterFunction():
theVariable = 0
def InnerFunction():
# use theVariable from OuterFunction somehow
# the solution is not to use InnerFunction(theVariable) due to the reasons given in the text
InnerFunction()
My hopes were there is some keyword (like global) or a way to tell the interpreter to use theVariable from the outer method's scope.
Why I need it this way:
A Python script that we run before has to become module now (the collection of methods).
OuterFunction did not exist before and InnerFunction is just an example for a big number of very complex methods that bear an already existing logic.
theVariable is just an example for multiple global variables that were used in the script in all of methods that InnerFunction represents.
I do not want to change signatures of all methods, that are, by the way, nested.
EDIT:
Here is the code that crashes for me in every interpreter, with "local variable 'theVariable' referenced before assignment" error (so I could not just reference the variable):
def OuterFunction():
theVariable = 5
def InnerFunction():
theVariable = theVariable + 1
print(theVariable)
InnerFunction()
OuterFunction()
EDIT2:
Seems trying to change the variable leads to the exception, which gives a wrong description.
If InnerFunction() is changed to contain only print(theVariable) statement it works.
You can just reference the variable directly, as follows;
def outer():
x = 1
def inner():
print(x + 2)
inner()
outer()
Prints: 3
You could simply reference the 'theVariable' inside the nested InnerFunction, if you don't want to pass it's value as a parameter:
def OuterFunction():
# Declare the variable
theVariable = 42
def InnerFunction():
# Just reference the 'theVariable', using it, manipulating it, etc...
print(theVariable)
# Call the InnerFunction inside the OuterFunction
InnerFunction()
# Call the OuterFunction on Main
OuterFunction()
# It will print '42' as result
Would this be okay with you:
def OuterFunction():
theVariable = 0
def InnerFunction(value):
return value + 1
theVariable = InnerFunction(theVariable)
return theVariable
This way you don't have to mess with scopes and your functions are pure.

How to Access Function variables in Another Function [duplicate]

This question already has answers here:
How do I get a result (output) from a function? How can I use the result later?
(4 answers)
Closed 4 months ago.
I have a small issue while calling multiple variables in python one function to another. Like I have to access the variable of xxx() variables in yyy(). Help me to do this.?
Example :
def xxx():
a=10
b=15
c=20
def yyy():
xxx()
print a ### value a from xxx()
print b ### value b from xxx()
yyy()
Return them from your first function and accept them in your second function. Example -
def xxx():
a=10
b=15
c=20
return a,b
def yyy():
a,b = xxx()
print a ### value a from xxx()
print b ### value b from xxx()
yyy()
You can't. Variables created in a function are local to that function. So if you want function yyy to get the values of some variables defined in function xxx then you need to return them from xxx, as demonstrated in Sharon Dwilif K's answer. Note that the names of the variables in yyy are irrelevant; you could write:
def yyy():
p, q = xxx()
print p ### value a from xxx()
print q ### value b from xxx()
and it would give the same output.
Alternatively, you could create a custom class. Briefly, a class is a collection of data together with functions that operate on that data. Functions of a class are called methods, the data items are known as attributes. Each method of a class can have its own local variables, but it can also access the attributes of the class. Eg
class MyClass(object):
def xxx(self):
self.a = 10
self.b = 15
self.c = 20
def yyy(self):
self.xxx()
print self.a
print self.b
#Create an instance of the class
obj = MyClass()
obj.yyy()
output
10
15
Please see the linked documentation for more information about classes in Python.
Try this:
def xxx():
a=10
b=15
c=20
return a, b
def yyy():
a, b = xxx()
print a
print b
yyy()
Or this:
def xxx():
global a, b
a=10
b=15
c=20
def yyy():
print a
print b
xxx()
yyy()
For more info, use help('return') and help('global'), or see this and this question.
And only use global when you need the variable can use at everywhere or you need the function return other things. Because modifying globals will breaks modularity.
pickle.dump-workaround
In general, I'm working with a return statement if I need the variable for another function or a script.
But especially if I want to investigate why my code is failing with new data I'd like to analyze the parameters without rebuilding all the code.
My solution is just to store the file on disk.
def xxx():
a=10
tmp_dir = os.path.join(os.getcwd(),'tmp')
if not os.path.exists(tmp_dir):
os.mkdir(tmp_dir)
pickle.dump(a, open(os.path.join(tmp_dir,'a.pickle'), 'wb'))
b=15
c=20
Then you may load the parameter from where ever you want. In my case usually from a Jupyter-Notebook for the analyses.
def yyy():
a = pickle.load(open(os.path.join(tmp_dir,'a.pickle'), 'rb'))
print a ### value a from xxx()
print b
Btw: this is for sure a construction I would only use to analyze errors.
The answers people gave above are correct. But from a design perspective this is not something correct. Method local variables are mean to be local. If at all there is something that needs to be shared across a file or some set of methods I suggest you use file level variables or constants.
Use the global keyword, like the following example:
global a=0
global b=0
global c=0
def xxx():
a=10
b=15
c=20
return a,b
def yyy():
print a
print b
xxx()

How to create variables local to with statement?

I would like to create temporary variables visible in a limited scope.
It seems likely to me that you can do this with a "with" statement, and I would think there is a construct that makes it easy to do, but I cannot seem to find it.
I would like something like the following (but it does not work this way of course):
pronunciation = "E_0 g z #_1 m p l"
# ...
with pronunciation.split() as phonemes:
if len(phonemes) > 2 or phonemes[0].startswith('E'):
condition = 1
elif len(phonemes) < 3 and phonemes[-1] == '9r':
condition = 2
So is there a simple way to make this work, using built-ins?
Thanks!
Python creates local variables with function scope (once a name is used it stays alive until the end of the function).
If you really want to limit scope then "del <var>" when you want it explicitly discarded, or create separate function to act as a container for a more limited scope.
You can create a method
def process_pronunciation(pronunciation):
phonemes = pronunciation.split()
if len(phonemes) > 2 or phonemes[0].startswith('E'):
condition = 1
elif len(phonemes) < 3 and phonemes[-1] == '9r':
condition = 2
return condition
When you call the method, the local variable phonemes won't be available in the global namespace.
pronunciation = "E_0 g z #_1 m p l"
condition = process_phonemes(pronunciation)
You could do it with with, but I don't think it's worth the trouble. Basically (in a python function) you have two scopes - global or local, that's it. If you want a symbol to have a lifespan shorter than the function you'll have to delete it afterwards using del. You could define your own context manager to make this happen:
class TempVar:
def __init__(self, loc, name, val):
self.loc = loc
self.name = name
self.val
def __enter__(self):
if self.name in self.loc:
self.old = self.loc[self.name]
self.loc[self.name] = self.val
def __exit__(self, *exc):
if hasattr(self, "old"):
self.loc[self.name] = self.old
else:
del self.loc[self.name]
then you can use it to get a temporary variable:
with TempVar(locals(), "tempVar", 42):
print(tempVar)
The working is that it modifies the dict containing local variables (which is supplied to the constructor via locals()) on entry and restoring it when leaving. Please note that this relies on that modifying the result returned by locals() actually modifies the local namespace - the specification does NOT guarantee this behaviour.
Another (and safer) alternative that was pointed out is that you could define a separate function which would have it's own scope. Remember it's perfectly legal to nest functions. For example:
def outer():
def inner(tempVar):
# here tempVar is in scope
print(tempVar)
inner(tempVar = 42)
# here tempVar is out of scope
with statement does not have its own scope , it uses the surrounding scope (like if the with statement is directly inside the script , and not within any function, it uses global namespace , if the with statement is used inside a function, it uses the function's namespace(scope)).
If you want the statements inside a with block to run in its own local scope, one possible way would be to move the logic to a function , that way the logic would be running in its own scope (and not the surrounding scope of with.
Example -
def function_for_with(f):
#Do something.
with pronunciation.split() as phonemes:
function_for_with(phonemes)
Please note, the above will not stop phonemes from being defined in the surrounding scope.
If you want that as well (move the phonemes into its own scope), you can move the complete with statement inside a function. Example -
def function_with(pronunciation):
with pronunciation.split() as phonemes:
#do stuff
pronunciation = "E_0 g z #_1 m p l"
function_with(pronunciation)
Expanding on #skyking's answer, here's an even more magical implementation of the same idea that reads almost exactly like you wrote. Introducing: the with var statement!1
class var:
def __init__(self, value):
import inspect
self.scope = inspect.currentframe().f_back.f_locals
self.old_vars = set(self.scope.keys())
self.value = value
def __enter__(self):
return self.value
def __exit__(self, type, value, traceback):
for name in set(self.scope.keys()) - self.old_vars:
del self.scope[name]
### Usage:
line = 'a b c'
with var (line.split()) as words:
# Prints "['a', 'b', 'c']"
print(words)
# Causes a NameError
print(words)
It does all the nasty extracting of local variables and names for you! How swell. If you space it quirkily like I did and hide the definition in a from boring_stuff import * statement, you can even pretend var is a keyword to all of your confused co-workers.
[1] If you actually use this, the ghost of a dead parrot will probably haunt you forever. The other answers provide much saner solutions; this one is more of a joke.

Method Overriding?

I saw this particular piece of code:
def g(x,y):
return x+y
def g(x,y):
return x*y
x,y=6,7
print (g(x,y))
The output is obviously(but not to me) is 42. Can somebody please explain this behavior? This is method overriding I suppose, but I'm still not getting the flow here.
When you define a function, and you redefine it, it will use the last one you defined, even the parameter is different:
def g(x,y):
return x+y
def g(x,y):
return x*y
x,y=6,7
print (g(x,y))
def hello():
return 'hello'
def hello():
return 'bye'
print hello()
def withone(word):
return word
def withone():
return 1==1
print withone('ok')
Output:
42
bye
TypeError: withone() takes no arguments (1 given)
And function name in Python is more like simple variable:
def hello():
return 'hello'
iamhello = hello # bind to the old one
def hello():
return 'bye'
print hello() # here is the new guy
print iamhello()
OutPut:
bye
hello
The devil is in the order of function definitions.
This is not technically method overriding as that requires class inheritance, instead it's a result of how python declares and references functions.
When declaring a function, python stores a reference to that function in a variable named after the function definition. (e.g. variable would be "foo" for "def foo():")
By declaring the function twice, the value of that variable gets overwritten by the second definition.
A Python script is parsed from top till bottom.
So anytime the same name of a variable or function or class occurs, it overwrites any definitions that where associated with this name before.
def g(x,z):
print('first')
def g():
print('second')
g = 3
print g
print g()
So look at this example which will result in the printout of '3' and then in an Exception: 'TypeError: 'int' object is not callable'
The name g is at first a function with two parameters, then it gets redefined to be a function with no parameters, then it gets redefined to be an int.
Which cannot be called obviously :)
Everything in python is treated as object, whether it be a function name or class name. So, when we define a function using 'def', the memory allocation is done for that method. Then python points the name that we assign to the function, to this allocated memory location. So if we define a method :-
def demo():
print 'hi'
the memory is allocated for the method, and the name 'demo' is pointed to its memory location as follows :-
Now as described by zoosuck in his second example, when you assign the function name to another variable :-
demo2 = demo # bind to the old one
then in that case, the assigned memory location to demo, is assigned to demo2 as well. So both demo and demo2 points to same location 12506.
print id(demo) # will print 12506
print id(demo2) # will print 12506
Now if we modify the above piece of code and in the next line, define a new method with same name demo:-
def demo():
print 'hi'
demo2 = demo # bind to the old one
demo() # Will print hi
def demo():
print "hello"
demo() # Will print hello
demo2() # Will print hi
then a completely new memory location 12534 is allocated for this new method, and now demo will point to this new location 12534 instead of pointing to the old one i.e. to 12506. But demo2 is still pointing to the location 12506.
I hope this will give you a clear idea of what is going on and how the method name is over-written.
Order matters, if names are same,last function you defined is processing. In your case it's;
def g(x,y):
return x*y
g is just a variable. The fact that the object it refers to is a function doesn't make it special in Python, so you can assign and reassign it as you want. In this case, the second assignment (which is what a function definition is) simply replaces the object stored there with a different one.
Functions and methods are normal objects like any others. So in
def g(x, y):
return x + y
def g(x, y):
return x * y
the second object g will override(replace) the first one, just like object a does below:
a = 1
a = 2
The number, type or order of parameters does not make any difference, because Python does not support function/method override and does not allow two functions/methods to have the same name.
If you are familiar with lambda function, also often called anonymous\inline functions, this might clear things up a bit
These two code blocks are essentially equal
def g(x,y):
return x+y
def g(x,y):
return x*y
g = lambda x,y: x+y
g = lambda x,y: x*y

Do you change variables AFTER you run a function in python?

So I wrote this function from a book I am reading, and this is how it starts:
def cheese_and_crackers(cheese_count, boxes_of_crackers):
print "You have %d cheeses!" % cheese_count
print "You have %d boxes of crackers!" % boxes_of_crackers
print "Man that's enough for a party!"
print "Get a blanket.\n"
ok, makes sense. and then, this is when this function is run where I got a little confused and wanted to confirm something:
print "OR, we can use variables from our script:"
amount_of_cheese = 10
amount_of_crackers = 50
cheese_and_crackers(amount_of_cheese, amount_of_crackers)
the thing that confused me here is that the amount_of_cheese and amount_of_crackers is changing the variables (verbage? not sure if i am saying the right lingo) from cheese_count and boxes_of_crackers repectively from the first inital variable labels in the function.
so my question is, when you are using a different variable from the one that is used in the initial function you wrote, why would you change the name of the AFTER you wrote out the new variable names? how would the program know what the new variables are if it is shown after it?
i thought python reads programs top to bottom, or does it do it bottom to top?
does that make sense? i'm not sure how to explain it. thank you for any help. :)
(python 2.7)
I think you are just a bit confused on the naming rules for parameter passing.
Consider:
def foo(a, b):
print a
print b
and you can call foo as follows:
x = 1
y = 2
foo(x, y)
and you'll see:
1
2
The variable names of the arguments (a, b) in the function signature (1st line of function definition) do not have to agree with the actual variable names used when you invoke the function.
Think of it as this, when you call:
foo(x, y)
It's saying: "invoke the function foo; pass x in as a, pass y in as b". Furthermore, the arguments here are passed in as copies, so if you were to modify them inside the function, it won't change the values outside of the function, from where it was invoked. Consider the following:
def bar(a, b):
a = a + 1
b = b + 2
print a
x = 0
y = 0
bar(x, y)
print x
print y
and you'll see:
1
2
0
0
The script runs from top to bottom. The function executes when you call it, not when you define it.
I'd suggest trying to understand concepts like variables and function argument passing first.
def change(variable):
print variable
var1 = 1
change(var1)
In the above example, var1 is a variable in the main thread of execution.
When you call a function like change(), the scope changes. Variables you declared outside that function cease to exist so long as you're still in the function's scope. However, if you pass it an argument, such as var1, then you can use that value inside your function, by the name you give it in the function declaration: in this case, variable. But it is entirely separate from var! The value is the same, but it is a different variable!
Your question relates to function parameter transfer.
There are two types of parameter transfer into a function:
By value ------- value changed in function domain but not global domain
By reference ------- value changed in global domain
In python, non-atomic types are transferred by reference; atomic types (like string, integer) is transferred by value.
For example,
Case 1:
x = 20
def foo(x):
x+=10
foo()
print x // 20, rather than 30
Case 2:
d = {}
def foo(x): x['key']=20
foo(d)
print d // {'key': 20}

Categories

Resources