Call a nested function through a global function? - python

I am new to Python and am trying to make a simple game with several chapters. I want you to be able to do different things depending on the chapter, but always be able to e.g. check your inventory. This is why I have tried using nested functions.
Is it possible to create a global function which acts differently depending on what chapter I am in, while still having certain options available in all chapters or should I perhaps restructure my code significantly?
I get the following error code:
> Traceback (most recent call last): File "test.py", line 21, in
> <module>
> chapter1() File "test.py", line 19, in chapter1
> standstill() File "test.py", line 4, in standstill
> localoptions() NameError: name 'localoptions' is not defined
I understand that the global function doesn't identify a nested function. Is there any way to specify this nested function to the global function?
def standstill():
print("What now?")
print("Press A to check inventory")
localoptions()
choice = input()
if choice == "A":
print("You have some stuff.")
else:
localanswers()
def chapter1():
def localoptions():
print("Press B to pick a flower.")
def localanswers():
if choice == "B":
print("What a nice flower!")
standstill()
chapter1()

I used classes as Mateen Ulhaq suggested and solved it. Thank you! This is an example of a scalable system for the game.
(I am new to Python and this might not be the best way, but this is how I solved it now.)
class chapter1:
option_b = "Pick a flower."
def standstill():
print("What do you do now?")
print("A: Check inventory.")
if chapter1active == True:
print("B: " + chapter1.option_b)
#Chapter 1
chapter1active = True
standstill()
chapter1active = False

Related

NameError: name 'furnish' is not defined Python

def getType():
inp=int(input("\t<<<<<APARTMENT RENTAL PROGRAM>>>>>\n1 studio\n2 One-Bedroom\n3 Two-Bedroom\n4 Exit\nEnter Your Choice ::"))
while(inp>4 or inp<0):
print("Enter Valid Choice!!")
inp=int(input("\t<<<<<APARTMENT RENTAL PROGRAM>>>>>\n1 studio\n2 One-Bedroom\n3 Two-Bedroom\n4 Exit\nEnter Your Choice ::"))
if(inp==4):
return 4,0
furnished=input("Do you want the apartment furnished(Y/N)?")
valid=['y','n','Y','N']
while(furnished not in valid):
print("Enter Valid Choice!!")
furnished = input("Do you want the apartment furnished(Y/N)?")
if(furnished == 'Y' or furnished=='y'):
return inp,1
return inp,0
def determineRent(kind,furnish):
rents=[[400,600,750],[500,750,900],[600,925,1025]]
return rents[kind-1][0],rents[kind-1][furnish+1]
def displayRent(kind,furnish,rent,deposit):
if(kind==1):
print("\tStudio")
elif (kind == 2):
print("\tOne-Bedroom")
elif(kind==3):
print("\tTwo-Bedroom")
**if (furnish == 1):
print("\tFurnished")**
else:
print("\tUnfurnished")
print("\tDeposit : $",deposit)
print("\tRent : $",rent)
I am trying to get rid of my syntax issues and I cannot get my statement to work (bolded) I included the entire code for reference. I tried redefining furnish and changing it to furnished to no avail.
Code inside function definitions (indented under a def statement) is not executed until you call those functions, so will not cause NameErrors when running the program. I'm not sure if this is your intention, but based on the way you have your code indented above, the only code that is being executed is the final if statement and 2 print statements. This should make it clearer:
def getType():
*** definition of getType function ***
def determineRent(kind,furnish):
*** definition of determineRent function ***
def displayRent(kind,furnish,rent,deposit):
*** Definition of displayRent function ***
if (furnish == 1):
print("\tFurnished")
else:
print("\tUnfurnished")
print("\tDeposit : $",deposit)
print("\tRent : $",rent)
Since you never call the getType, determineRent, or displayRent functions, the interpreter just passes through storing those in memory without attempting to actually execute the code. So the first line it actually attempts to execute is:
if (furnish == 1):
But you haven't defined a variable called furnish at this point. That's why you get the NameError. If you write furnish = 1 above this line you'll see that it works (but next you get NameError for deposit instead).
while(furnished not in valid):
print("Enter Valid Choice!!")
That looks like an infinite loop to me :)
Assuming that these are functions called from another module, and that the code erroring out was suposed to be inside the displayRent function, your problem is indentation.
Python has an indentation based syntax, which means that your spaces/tabs at the beginning of the line matter a lot. In this case you have none on your line if (furnish == 1): and on the next lines, which means that Python will understand that they should be considered at the global level of that module. If you want it to be within the displayRent function you need to indent correctly, i.e. add leading tab/spaces to match the rest of the function code. Like this:
def getType():
inp=int(input("\t<<<<<APARTMENT RENTAL PROGRAM>>>>>\n1 studio\n2 One-Bedroom\n3 Two-Bedroom\n4 Exit\nEnter Your Choice ::"))
while(inp>4 or inp<0):
print("Enter Valid Choice!!")
inp=int(input("\t<<<<<APARTMENT RENTAL PROGRAM>>>>>\n1 studio\n2 One-Bedroom\n3 Two-Bedroom\n4 Exit\nEnter Your Choice ::"))
if(inp==4):
return 4,0
furnished=input("Do you want the apartment furnished(Y/N)?")
valid=['y','n','Y','N']
while(furnished not in valid):
print("Enter Valid Choice!!")
furnished = input("Do you want the apartment furnished(Y/N)?")
if(furnished == 'Y' or furnished=='y'):
return inp,1
return inp,0
def determineRent(kind,furnish):
rents=[[400,600,750],[500,750,900],[600,925,1025]]
return rents[kind-1][0],rents[kind-1][furnish+1]
def displayRent(kind,furnish,rent,deposit):
if(kind==1):
print("\tStudio")
elif (kind == 2):
print("\tOne-Bedroom")
elif(kind==3):
print("\tTwo-Bedroom")
if (furnish == 1):
print("\tFurnished")
else:
print("\tUnfurnished")
print("\tDeposit : $",deposit)
print("\tRent : $",rent)
Documentation for reference and better understanding: Python Docs - Indentation

Error: UnboundLocalError: local variable 'attempts' referenced before assignment

I am attempting to make a simple guessing game for my class with graphics and I'm trying to make an attempt counter. This is the area where my code is going wrong.
def value():
guess = int(input("Enter your guess: "))
if guess > num:
attempts = attempts + 1
turtle.clearscreen()
interface()
tooHigh()
attempt = turtle.Turtle()
attempt.speed(0)
attempt.color("white")
attempt.penup()
attempt.hideturtle()
attempt.goto(-250 , 200)
attempt.write(guess, font=("Courier", 14, "bold"))
value()
elif guess < num:
attempts = attempts + 1
turtle.clearscreen()
interface()
tooLow()
attempt = turtle.Turtle()
attempt.speed(0)
attempt.color("white")
attempt.penup()
attempt.hideturtle()
attempt.goto(-250 , 200)
attempt.write(guess, font=("Courier", 14, "bold"))
value()
elif guess == num:
attempts = attempts + 1
turtle.clearscreen()
interface()
yes()
attempt = turtle.Turtle()
attempt.speed(0)
attempt.color("pink")
attempt.penup()
attempt.hideturtle()
attempt.goto(-250 , 200)
attempt.write(guess, font=("Courier", 14, "bold", "underline"))
print ("Correct!")
else:
print ("ERROR")
def startScreen():
begin = input("Start the game?: ")
if begin == 'yes':
value()
elif begin == 'instructions':
instructions()
startScreen()
elif begin == 'no':
sys.exit()
else:
print ("Unrecognised answer.")
startScreen()
attempts = 0
num = random.randint(1,1000)
interface()
startScreen()
The error I receive is:
Traceback (most recent call last):
File "D:\Desktop\Python Programs\Game.py", line 154, in <module>
`startScreen()`
File "D:\Desktop\Python Programs\Game.py", line 141, in startScreen
`value()`
File "D:\Desktop\Python Programs\Game.py", line 110, in value
`attempts = attempts + 1`
UnboundLocalError: local variable 'attempts' referenced before assignment
It doesn't seem possible to move attempts into the function as it constantly calls itself, resetting attempts each time.
I am unsure why this is occurring so any help would be greatly appreciated. Thanks!
The reason you are getting this error is because of something called variable scope. You have defined the variable attempts outside of the function value, so the function will not recognize any local variable by the name attempts unless you explicitly put the statement global attempts at the beginning of your function. This will tell the function that you want to use the variable attempts that you defined in your main program. That should look like this:
def value():
global attempts
#function code
Alternatively, you can allow your function value to take an argument, and pass the variable attempts into that. That would look something like this:
def value(attempts):
#function code
#you can use the variable attempts as needed, since you're passing it directly into the function
#call the function however you want
attempts = 0
value(attempts)
In the function, when you access a variable for assignment, it by-default is treated as a local variable. So, to make Python know that the variable that you want to modify is a global variable, you do the following:
def value():
global attempts
# rest of your code

'function' object is not subscriptable error message

I am new to python and I am trying to make a basic text game with an inventory system. It was all going perfectly until I realised I needed the whole inv system as a function instead, and that's where the problems started.
gloinv = ["apple (food) 5", "health (healthpotion) 10", "sword (weapon) 5"]
hunger = 5
health = 10
fighting = False
enemyLife = 0
def get_num(x):
return (int(''.join(ele for ele in x if ele.isdigit())))
def inv():
global gloinv
global inv
print(gloinv)
while True:
item = input("which item would you like to select? ")
select = inv[int(item)-1]
print("you have selected '", select,"'")
use = input("type 'use' to use it or 'back' to select another. ")
if use == "use":
if "(food)" in select:
y = (int(''.join(ele for ele in select if ele.isdigit())))
print("you have eaten", (select.split(' ', 1)[0] ), "your hunger is now", hunger + y)
inv.remove(select)
print(inv)
gloinv = inv
break
elif "(healthpotion)" in select:
y = (int(''.join(ele for ele in inv[int(item)-1] if ele.isdigit())))
print("you have drunk", (inv[int(item)-1].split(' ', 1)[0] ), "your health is now", health + y)
health = health + y
inv.remove(inv[int(item)-1])
print(inv)
gloinv = inv
break
elif "weapon" in inv[int(item)-1]:
if fighting == True:
enemyLife - get_num(inv[int(item)-1])
elif fighting == True:
print("you can't use a weapon here")
break
elif use == "back":
print(inv)
inv()
print(gloinv)
print(hunger)
print(health)
I've tried to adapt to some problems but when I run this it comes up with;
Traceback (most recent call last):
File "C:\Users\Jenson\Desktop\Python\inv.py", line 47, in <module>
inv()
File "C:\Users\Jenson\Desktop\Python\inv.py", line 19, in inv
select = inv[int(item)-1]
TypeError: 'function' object is not subscriptable
enter code here
>>>
I have looked on other questions on this site but they are too confusing for me and tailored to different code doing different things.
Thanks for the answers but I found the solution doing some testing of my own. What I did wrong was label the function (inv) the same thing as the variable (inv) I solved it by naming the variable vInv instead so python wouldn't confuse the two.
Use parentheses (()) and not brackets ([]) when making a function call.
On line 19, you are doing the following:
select = inv[int(item)-1]
First of all; it's not clear what the purpose of this is. Please double check it. If you want to call the inv function, you need to call it with parentheses () and add the method parameters to the function declaration. Right now you're treating a function as a list, and using int(item)-1 as the index of that list. Hence the error.

Using functions with variables in Python

I had an assessment for my programming class about calculating insurance using functions. This is the code I was trying to get work but unfortunately I failed:
import time
def main():
print('Welcome to "Insurance Calculator" ')
type_I, type_II, type_III = inputs()
calculationAndDisplay()
validation()
time.sleep(3)
def inputs():
try:
type_I = int(input("How many Type I policies were sold? "))
type_II = int(input("How many Type II policies were sold? "))
type_III = int(input("How many Type III policies were sold? "))
return type_I, type_II, type_III
except ValueError:
print("Inputs must be an integer, please start again")
inputs()
def calculationAndDisplay():
type_I *= (500/1.1)
type_II *= (650/1.1)
type_III *= (800/1.1)
print("The amount of annual earned for type_I is: $", type_I)
print("The amount of annual earned for type_I is: $", type_II)
print("The amount of annual earned for type_I is: $", type_III)
def validation():
cont = input("Do you wish to repeat for another year? [Y/N]: ")
if cont == 'Y' or cont == 'y':
main()
elif cont == 'N' or cont == 'n':
print('Thank You! ------ See You Again!')
else:
print("I'm sorry, I couldn't understand your command.")
validation()
main()
I eventually got it to work by cramming all of the input, calculation, and display into one function. I just want to know how I could have made it work the way intended..
Edit: The program is meant to get the user to input the number of policy's sold and display a before tax total. When I enter a few number inputs it gives me the following error
Welcome to "Insurance Calculator"
How many Type I policies were sold? 3
How many Type II policies were sold? 3
How many Type III policies were sold? 3
Traceback (most recent call last):
File "C:\Users\crazy\Desktop\assessment 2.py", line 38, in <module>
main()
File "C:\Users\crazy\Desktop\assessment 2.py", line 5, in main
type_I, type_II, type_III = inputs()
TypeError: 'NoneType' object is not iterable
Edit: I moved the return line to the suggested line and now it is giving me an unbound variable error:
Welcome to "Insurance Calculator"
How many Type I policies were sold? 5
How many Type II policies were sold? 5
How many Type III policies were sold? 5
Traceback (most recent call last):
File "C:\Users\crazy\Desktop\assessment 2.py", line 39, in <module>
main()
File "C:\Users\crazy\Desktop\assessment 2.py", line 6, in main
calculationAndDisplay()
File "C:\Users\crazy\Desktop\assessment 2.py", line 22, in
calculationAndDisplay
type_I *= (500/1.1)
UnboundLocalError: local variable 'type_I' referenced before
assignment
The problem is, that you save the values in variables which only exist inside the main method but not in the global scope:
type_I, type_II, type_III = inputs()
calculationAndDisplay()
Doing this, the calculationAndDisplay() method do not know the values. You can solve this, by adding parameters to this functions, like this:
def calculationAndDisplay(type_I, type_II, type_III):
#your code
Edit: You code is working without any problem when you perform all calculations in the same method, as now all variables are created inside the same scope. If you use methods, you either have to use function arguments/parameters (the better solution) or use global variables (bad solution, as it undermines the concept of the functions).
In the case, that you later on want to use the modified values of type_I etc. after calling calculationAndDisplay() again, you have to return the modified values in this function, so that you and up with this code:
def calculationAndDisplay(type_I, type_II, type_III):
#your code
return type_I, type_II, type_III
That error which you have mentioned is due to the indentation of the return statement in inputs(). That return statement should be inside inputs function(Because in your case inputs() is not returning type_I,type_II,type_II). Also arguments should be passed to calculationAndDisplay(type_I,type_II,type_III).

Error saying a variable is not defined?

#Intro
import time
import random
def restart():
bowlSize = random.randint(1,100)
bowlStrawberries = 0
def lel():
while bowlSize > bowlStrawberries:
if (addCheck + bowlStrawberries) > bowlSize:
print('You´re filling the bowl..')
time.sleep(2)
print('...and...')
time.sleep(2)
print('Your mom slaps you!')
restart()
def addStrawberries():
print('The bowl has ' + str(bowlStrawberries) + ' strawberries in it')
print('How many strawberries do you want to add?')
addCheck = input()
lel()
print('STRAWBERRY (:')
time.sleep(2)
print('Okey so you have a bowl kinda')
time.sleep(2)
print('And you have a bag with 100 strawberries')
time.sleep(2)
print('So ur mom forces you to fill the bowl')
time.sleep(2)
print('But she will slap you if a strawberry drops on the floor')
time.sleep(2)
print('So you have to fill it up in as few tries as possible without overfilling it')
time.sleep(2)
restart()
addStrawberries()
I´m new to Programming, it´s my fifth day today and I can´t understand why I get errors. You propably had similar questions but I am new and I don´t know what to search. I basically want it to restart when I pick a higher value than the bowls space.
Exact errors:
Traceback (most recent call last):
File "C:/Users/***/Documents/strenter code herew.py", line 44, in <module>
addStrawberries()
File "C:/Users/***/Documents/strw.py", line 27, in addStrawberries
lel()
File "C:/Users/***/Documents/strw.py", line 14, in lel
if (addCheck + bowlStrawberries) > bowlSize:
NameError: name 'addCheck' is not defined
addCheck is a local variable in addStrawberries, meaning it can't be seen outside of the function. I recommend passing it as an argument to lel, i.e. call lel(addCheck) and define lel as def lel(addCheck). Alternatively you could make addCheck a global variable by inserting the statement global addCheck in addStrawberries before assigning it, but global variables tend to be icky.

Categories

Resources