functions in python - need explanation - python

can someone simply explain functions in python? I just can't get my head around them.
So I have had a go at them, and this is what I've ended up with, but it keeps saying that character is not a global variable
def char_name():
character = input("Enter character name: ")
return character;
def main():
char_name()
print(character)
main()
Can anyone explain functions?

This part is a function:
def char_name():
character = input("Enter character name: ")
return character;
It's important to realize that the variable character exists only inside the function. Not outside of it. That's a great feature -- it means that if you decide that name is a better name for the variable after all, then you only need to change the variables inside the function, and guaranteed nowhere else. No assignments to variables elsewhere can influence what happens in your function. It's all there.
The function has a return value equal to the value of the variable at the end of the function.
def main():
char_name()
print(character)
And here's another function, that also tries to have a variable named character. It happens to have the same name, but that's just a coincedence, it's a different function so it's a different variable. Unfortunately, this variable is only used but never set to any value, and Python can't find it as a global variable either, so it throws an exception. char_name is called, but its return value is not used for anything, so it's discarded.
What you want to do is this:
def main():
name = char_name() # I picked a different name to make my point
print(name)
The function char_name is called, and its return value is assigned to the variable name. Now you can print it.

def char_name():
character = input("Enter character name: ")
return character
def main():
character = char_name()
print(character)
main()
You need to assign returned values.

Related

Return variable from a function

This section of a program I am writing is supposed to take the random choice and then print it outside the function (I can't print from within as I need the variable later).
I am sure there is a simple solution to this, but I am unsure what it is.
#python2
def CompTurn():
RandTurn = [Column1,Column2,Column3,Column4]
Choice = random.choice(RandTurn)
return(Choice)
print Choice
Thank you.
Add the line
Choice = CompTurn()
before your print statement. Because the variables you declare within the function are not known outside of it, you have to store (or print directly, but then you cannot store it) the returned variable in a new variable.
You have defined your function correctly, but you never executed it! (You'll see that if you make it print something as a diagnostic.) You must run it to get the result:
chosen = CompTurn()
print chosen
Note that I used a different variable name. You could use the same variable name as a variable in your function, but it's still a different variable than the one in your function.
It is also important to realize that your function returns a value, not a variable. You can assign the value to a variable (as above) or print it immediately.
print CompTurn()
About your program, you don't need the brackets for return. It's s statement, not a function.
def CompTurn():
RandTurn = [Column1,Column2,Column3,Column4]
Choice = random.choice(RandTurn)
return Choice
Shorter:
def CompTurn():
RandTurn = [Column1,Column2,Column3,Column4]
return random.choice(RandTurn)
To print the return value, You can save it in a variable and print it
ret = CompTurn()
print ret
Or print directly:
print CompTurn()

Error message saying variable not defined when it is. Python

I am trying to create a simple encryption program in python using functions but am having a problem where I get an error message when I run the program saying ('msgReversed' is not defined) when it is.
the program works by first reversing the users message and then shifting the letters to the value of the Key
alphabet=("abcdefghijklmnopqrstuvwxyz ")
def userInput():
plaintext=input("Enter message to encript")
k=int(input("Enter encription Key you want to use (1-25)"))
return (k,plaintext)
def reverseMsg(plaintext):
msgReversed=''
leng=len(plaintext)-1
for c in plaintext:
msgReversed+=plaintext[leng]
leng=leng-1
print(msgReversed)
return(msgReversed)
def encript(msgReversed,k):
cipher=''
for c in msgReversed:
if c in alphabet:
cipher+=alphabet[(alphabet.index(c)+k)%(len(alphabet))]
print(cipher)
(k,plaintext)=userInput()
reverseMsg(plaintext)
(cipher)=encript(msgReversed,k)
Error Message reads as follows`:
Line 26, in <module>
(cipher)=encript(msgReversed,k)
NameError: name 'msgReversed' is not defined
As mentioned in my comment, your variable msgReversed is not declared outside of your function, so it is not defined when you call it outside of it. In order to avoid posting duplicate answers, here is another approach:
I do not know if you have worked with classes before, but here is an example and pythons official documentation (https://docs.python.org/2/tutorial/classes.html)
class Encrypt:
def __init__(self):
(k,plaintext)=self.userInput()
self.reverseMsg(plaintext)
cipher =self.encript(self.msgReversed,k)
def userInput(self):
plaintext=input("Enter message to encript")
k=int(input("Enter encription Key you want to use (1-25)"))
return (k,plaintext)
def reverseMsg(self, plaintext):
self.msgReversed=''
leng=len(plaintext)-1
for c in plaintext:
self.msgReversed+=plaintext[leng]
leng=leng-1
print(self.msgReversed)
return(self.msgReversed)
def encript(slf, msgReversed, k):
alphabet=("abcdefghijklmnopqrstuvwxyz ")
cipher=''
for c in msgReversed:
if c in alphabet:
cipher += alphabet[(alphabet.index(c)+k)%(len(alphabet))]
print(cipher)
Encrypt()
As for Global variables, you can declare a global within a function. all you have to do is declare it global:
variable_name global
so your function with your variable msgReversed would be as follows:
def reverseMsg(plaintext):
global msgReversed
msgReversed = ''
leng=len(plaintext)-1
for c in plaintext:
msgReversed+=plaintext[leng]
leng=leng-1
print(msgReversed)
return(msgReversed)
Change your last few lines from this:
reverseMsg(plaintext)
(cipher)=encript(msgReversed,k)
To this:
(cipher)=encript(reverseMsg(plaintext),k)
In your last line you pass a variable called 'msgReversed' into your 'encript' function. However: msgReversed is only locally defined inside your 'reverseMsg' function. Variables can either be local variables that only live inside of a function. Or global variables, that live in the entire script. A simple workaround would be to make your msgReversed a global variable, by simply adding 'global' in front of the first line of your 'reverseMsg' function. Another solution in your first to last line:
msgReversed = reverseMsg(plaintext)
A simplified tutorial on this matter: http://www.python-course.eu/global_vs_local_variables.php
Added a simple example:
myname = "Marc"
def printName():
myname = "Sonder"
print (myname)
printName()
print (myname)
Outside of the function, the 'myname' function will yield "Marc". However inside the function, myname will yield "Sonder". If you would delete the first line, and try to execute the last line, to print the global version of 'myname', you will get the exact same error as you have got right now.
To grasp this I would copy this script, and see what changes when you comment certain parts out.
When you return the msgReversed variable from the reverseMsg() function, you need to assign it to a new variable in the outside scope.
msgReversed = reverseMsg(plaintext)
(cipher)=encript(msgReversed,k)
I suspect the confusion arises with the following line:
return msgReversed # Note, the brackets aren't required here
This returns from the function reverseMsg() while passing out the variable msgReversed. However, this variable isn't assigned anywhere by default — the name msgReversed is specific to the function. To store a value returned from a function you need to provide a variable name to store it in. Hence the following:
msgReversed = reverseMsg(plaintext)
...will store the value returned from your function in a new variable named msgReversed. You could also name that variable something else:
this_is_another_msgReversed = reverseMsg(plaintext)
If you don't provide a variable to assign the value to, it is simply lost:
reverseMsg(plaintext)
# No msgReversed variable here

Local variable 'x' referenced before assignment

def main():
tests = get_initial_input(tests)
assignments = get_initial_input(assignments)
exercises = get_initial_input(exercises)
labs = get_initial_input(labs)
finals = get_initial_input(finals)
print(tests, assignments, labs)
def get_initial_input(x):
val = int(input("How many", x , "were there? "))
return val
main()
I keep getting an error:
UnboundLocalError: local variable 'tests' referenced before assignment
I've tried many different things to try to get tests to go to get_initial_input() but it says that it is referenced before assignment.
How is that possible when the first line of code I'm trying to define it?
When you use:
tests = get_initial_input(tests)
the first thing that happens is that Python tries to evaluate this:
get_initial_input(tests)
But tests is not defined yet, so you get an UnboundLocalError.
I think you are trying to pass a string to your function, which is used in the input prompt. A literal string is always surrounded by quotes.
tests = get_initial_input("tests")
This would be easier to debug if you'd used a proper variable name - eg label - in your function argument.
You are passing unassigned variable tests to get_initial_input() function. So, that's why you receive the error.
If you need a default value inside get_initial_input() function for x argument, then define it explicitly:
def get_initial_input(x=5):
...
And in main() call it for tests variable without arguments:
tests = get_initial_input()
If you need names (e.g. 'How many tests') - then pass strings, not cars to the function:
tests = get_initial_input('tests')

NameError when using a variable returned by a function

I want to return the variable aRoll, and use it as the argument for the next function. In this case, aRoll holds the answer to the question "Let's roll your ability scores. ready? (y/n)" Once the question is answered, it raw input is stored in the variable aRoll and returned.
import random
pAbility = ['Str', 'Dex', 'Con', 'Int', 'Wis', 'Cha']
pScore = []
i = 0
def pQuestion():
aRoll = raw_input("Let's roll your ability scores. ready? (y/n)")
if aRoll not in ('y', 'n'):
print "Please type 'y' or 'n'"
return pQuestion()
else:
return aRoll
def pStats(aRoll):
while aRoll == "y":
while i < 6:
pScore.append(random.randint(7, 18))
i = i + 1
for score, ability in zip(pAbility, pScore):
print str(score) + ":\t\t " + str(ability)
def pReroll():
aRoll = raw_input("Do you wish to reroll? (y/n)")
aRoll = aRoll.lower()
if aRoll not in ('y', 'n'):
print "Please type 'y' or 'n'"
return pReroll()
pQuestion()
pStats()
pReroll()
When putting print aRoll after pQuestion(), at the bottom of the script, it tells me aRoll isn't defined. Am I not returning aRoll correctly?
aRoll as defined is a separate local variable in each function. You either need to declare it as a global (not a good idea), or explicitly pass the return value of one function as an argument to the next. For example,
rv = pQuestion()
rv2 = pStats(rv)
rv3 = pReroll(rv2)
(Note the change in the definition of pReroll this requires.)
A couple of the other answers have it partly right, but you have to put their answers together to get what you want. At the bottom, it should look like this:
aRoll = pQuestion()
pStats(aRoll)
First, you're assigning what pQuestion() returns to aRoll. Next, you're passing that in as a parameter to pStats(). There are a couple things that will happen if you don't do this:
Since you defined a parameter for pstats(), the interpreter will tell you that you're missing a parameter when you try to run this.
Due to the local scope of aRoll, that variable is not defined outside of the function pQuestion().
For more information about variable scope, look here. This page may also prove useful:
http://gettingstartedwithpython.blogspot.com/2012/05/variable-scope.html
pQuestion() returns aRoll but you never assign the return value. pStats() expects you to pass in aRoll but you never do.
You don't return "the variable" but the value of the variable at the point of the return statement. The name of the variable in the function is completely irrelevant. This is a Good Thing: functions are a way to encapsulate pieces of code. Imagine a simple function that adds two numbers:
def add(a, b):
result = a+b
return result
and then the author changes his mind and renames the variable inside the function:
def add(a, b):
sum = a+b
return sum
and finally, he's clever and just does
def add(a, b):
return a+b
As a user of this function, you should not bother about the names inside the function. You use the add function because you expect it to return the sum of the arguments, no matter how the function works internally.
If you want to use the result of a function, you must store it in a variable yourself:
sum_of_2_and_3 = add(2,3)
print(sum_of_2_and_3)
Not to be discouraging, but your code is a long way from working even once we correct the issue with aRoll. You'll probably have to follow up with some other questions.
As for your immediate problem:
aRoll is defined in pQuestion() and only exists for the duration of that function call (it is in scope only within that function).
When you return aRoll in the function the name aRoll is lost and the value of aRoll "pops out" of the function into the calling code. Unfortunately, you're not catching that value so it basically dissolves into the ether, never to be seen again.
In order to catch the value you need to assign it, like this:
answer = pQuestion()
Now, you have a new variable called answer containing the value "popped out" of the function pQuestion() (y or n in this case). Note that you could also write aRoll = pQuestion() and you'd have a variable named aRoll containing the value from pQuestion() but, importantly, it would not be the same variable as the one INSIDE pQuestion() because that one was already lost. While you're learning, it's probably a better idea to use different variable names everywhere so you don't get confused and believe that the same-named variables are actually the same (rather than variables in different scopes that coincidentally share a name)
That's thing one. Next, you have somehow get the value of answer or aRoll or foobar or whatever name you gave to that value into pStats(). You've already told pStats() to expect to receive one value and to name that value aRoll -- but this aRoll, like the first one, is in scope only inside the pStats() function. The problem is, you're not actually supplying the value to pStats(), which you would do like this:
pStats(answer)
or
pStats(aRoll)
or
pStats(foobar)
or whatever name you chose for the variable.
There is another solution to this problem which is to declare the variables as global and not pass them around. I urge you not to pursue this solution as it leads to very bad programming habits and should only be used in rare circumstances after you fully understand the idea of local scope.

Python - function setting external variable to user input as side effect

I'm a casual gamer and hobbyist programmer who knows a bit of Python. I'm trying to make a simple text adventure game engine, so I need to get raw input from the player.
This is Python 3.2.2, so my line is this:
var = input("What do you want to do? ").lower()
And that line works, but rather than typing that whole line I'd like to make it into a function (something like "getinput()"). From what I've read about input() and functions I'm looking for a function that doesn't return anything, but changes another variable's state (here "var") as a "side effect."
I do have a working function "halt()" that takes no arguments:
def halt():
input("(Press Enter to continue...) ")
print("")
Calling "halt()" gives the prompt, waits for Enter, then prints a blank line and moves on, which I intended.
The function I'm trying to get to work looks like this:
def getinput(x):
x = input("What do you want to do? ").lower()
print("")
After defining getinput(x):
var = ""
getinput(var)
print(var)
That snippet does not print the user's input, and I'm confused as to why. What do I need to do to make this work in the intended fashion?
Is what I'm trying to do impossible with a function, or is there just something I don't know about scope? Should I be at codereview?
You are right that the issue is about scope. The x in this line:
x = input("What do you want to do? ").lower()
Does not change the value that is passed to it- it creates a new variable (also called x) in the local scope of the function.
The right way to do this would be:
def getinput():
return input("What do you want to do? ").lower()
x = getinput()
print(x)
NOTE: If you are going to use any version of Python before 3.x, definitely consider using the raw_input() function as the plain input() function only takes input that is SYNTACTICALLY VALID from the user, otherwise a SyntaxError will be raised.
I'm not sure what you're trying to do exactly, but I've moved around what you've written above so that it will work. Here's what I suggest trying:
First the function getinput()...
def getinput():
x = raw_input("What do you want to do? ").lower() #prompts for the value of x
print "" #prints a blank line
return x
Then the second part...
var = getinput()
print(var)
When you pass something to a Python function, it's generally impossible to modify it unless it's mutable. That restricts you to a small subset of Python types such as a list or dictionary.
def getinput(x):
x[0] = input("What do you want to do? ").lower()
print("")
var = [""]
getinput(var)
print(var[0])
You're far better off letting the function return a value. That's the way Python was meant to work.
var is a python string variable which is being passed by value to your getinput function, which means that your getinput function only modifies a local copy of the name "x", not the value pointed to by "x" from your calling scope.
Also in Python strings are immutable and so it is impossible to modify a string's underlying value in-place due to string interning/hash consing - you merely create a new string. You should really be returning your value:
x = getinput()
But if you still want to stick to your existing design, you can pass this string variable by reference by wrapping it in a list or other reference type:
def getinput(li):
li.append(input("What do you want to do? ").lower())
print("")
usage:
x = []
getinput(x)
print x[0]

Categories