return statement in python - python

I tried to code a program but ran into problem with the return statement.
The following lines of code raised an error message saying that the variable names is undefined.
However, I did use the return statement to return names and pass it to the main function:
def main(names):
names_in()
print(names)
# import the record, put it into a list, pass that list to main().
def names_in():
infile = open('names.txt','r')
names = infile.readlines()
infile.close()
index = 0
while index < len(names):
names[index] = names[index].rstrip('\n')
index += 1
return names
main(names)
I've written another program before that did the same thing and everything worked fine, so I'm not sure what's wrong here?

Your problem is here:
main(names)
You are calling your main function with a variable name that hasn't been defined yet. The error you're getting should display a line number that points to this line: that will validate this is where the problem is.
# 'names' is not defined in this scope
def main(names):
# Some code
# 'names' is a variable that is 'in scope' here because it's passed as an 'argument'
# 'names' is not defined in this scope either
# import the record, put it into a list, pass that list to main().
def names_in():
infile = open('names.txt','r')
names = infile.readlines() # defines 'names' for this scope
# more code
return names # because 'names' is defined it can return it
# 'names' is no longer defined in this scope
main(names) # This fails because when the compiler tries to resolve 'names' it can't find anything
Based on what you're apparently trying to do, you need to modify your main function like so:
def main():
print(names_in())
And call it like so:
main()
Note, too, you seem to have some confusion over how code is executed. If I write:
def a():
print("a")
def b():
print("b")
print("c")
b()
a()
It gets translated to something equivalent to:
print("c")
print("b")
print("a")
The def statements get copy-pasted, effectively, into where they are called.

Your main function should not take in any parameter. Instead, it should use the return value from names_in:
def main():
names = names_in()
print(names)
Later in your code:
main()

Related

Cannot use a variable that was returned from a function

Code is as follows:
def join_files(Fund):
Month_1 = pd.read_excel(Fund[0])
Month_2 = pd.read_excel(Fund[1])
Joined_1 = Month_1[["UNIQUE_ID","NET_AMOUNT"]].merge(Month_2[["UNIQUE_ID","NET_AMOUNT",]], on = "UNIQUE_ID", how = "left")
return Joined_1
join_files(GF)
print(Joined_1)
When I run the code, it gives me an error on the 'print(Joined_1)' line and says that it is an undefined name even though the code above runs successfully.
I know the function works since if I change the return statement to print() the output is printed.
That's because your variable of Joined_1 is contained with the join_files() function. After you return Joined_1, the value of that variable is returned (but not captured). Then you ask to print the variable, but at that point the script is no longer aware of the Joined_1 variable. I think you're looking for something more like this.
def join_files(Fund):
... // I haven't verified your your excel read logic
return(Joined_1)
ret_val = join_files(GF)
print(ret_val)
You could do a small test with this to get a template started for you:
def use_returned_value(some_val)
new_value = some_val
return new_value
return_value = use_returned_value(1234)
print(return_value)

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.

UnboundLocalError: local variable 'count' referenced before assignment

Throwing error at "count+=1". I tried making it a global etc. and it still gave an issue. It's more of a joke than anything, but I'd like to know why it isn't working.
import math
def delT():
#inputs
#float inputs
#do math
#print results
global count
count=0
def getAndValidateNext():
#print menu
getNext=input("select something")
acceptNext=["things","that","work"]
while getNext not in acceptNext:
count+=1
print("Not a listed option.")
if count==5:
print("get good.")
return
return(getAndVadlidateNext())
if getNext in nextRestart:
print()
return(delT())
if getNext in nextExit:
return
getAndVadlidateNext()
delT()
You need to move your global keyword down into your function.
count=0
def getAndValidateInput():
global count
#print menu
#So on and so forth
Now you should be able to access your count variable. It has to do with scoping in Python. You have to declare a variable is global in each function that you want to use it in, not just where it is define.
I ran into the same issue once, it turned out to have to do with the scope and having a function definition within another function definition. What worked was writing separate functions that would create and modify a global variable. Like this for example:
def setcount(x):
global count
count = x
def upcount():
global count
count += 1
global count should be inside the getAndValidateInput() function.

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

Assigning to global variable inside a function doesn't work

I'm newbie in Python programming and have a problem with global variables.
I have a code like this:
import ...
sentiment_words = {} #global variable
def getTweetSentiment(tweet_text):
sentiment = 0
words = extractWordsFromTweet(tweet_text)
for word in words:
if word in sentiments_words:
sentiment += sentiments_words[word] #sentiment_words is empty
return sentiment
def main():
global sentiment_words
sentiment_words = loadSentiments(open(sys.argv[1])) #setting new value
When I call getTweetSentiment function it doesn't see any variables inside sentiment_words. Could you please help me to understand how it should be written in right way?
Try to use class. It's better than using global variable.
You can access to sentiment_words this way sentimentTweet.sentiment_words.
Your code would look like:
class sentimentTweet:
def __init__(self,d={}):
sentiment_words = d
def getTweetSentiment(self,tweet_text):
sentiment = 0
words = extractWordsFromTweet(tweet_text)
for word in words:
if word in self.sentiments_words:
sentiment += self.sentiments_words[word] #sentiment_words is empty
return sentiment
sTwitter= sentimentTweet(loadSentiments(open(sys.argv[1]))) #u r creating an instance of the class and loading it
print sTwitter.sentiment_words #Check, Try to print sentiment_words values
In case you have a tweet text. You can run your function getTweetSentiment this way.
t= "tweet_text" #I'm not sure how do you use this variable
returnedSentiment= sTwitter.getTweetSentiment(t) #This is how you run your function
print t
Are you actually calling the main() function at any point? From the code you've provided, it doesn't look like you are, which means that loadSentiments() will not be run and thus sentiment_words will remain unchanged (i.e. it will remain defined as {}).
Unlike C/C++/Java, Python programs do not start with a main() function/method. Instead, the program is run from the first line to the last, so you'll need to add the following at the bottom of your file:
if __name__ == "__main__":
main()
This will ensure that the main() function is called if the file is executed directly.

Categories

Resources