Variables and Functions explanation for a beginner [closed] - python

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 months ago.
Improve this question
I don't know how functions work and would like help making sure that I can have the variable change depending on which 'person' is running the account. Can someone explain how to change the 'bad' variable so that it goes to a 'person 1' 'person 2' or 'person 3' depending on which the user chooses to enter?:
bal=500
lock=0
end=False
def atm():
while end==False:
if lock>=4:
while lockloop==True:
try:
print("Your balance is $",bal, sep='')
lk=int(input("Error, you have locked your account. Please enter funds until balance becomes positive: \n$"))
if lk<=0:
print("Please input a positive amount")
continue
bal=bal+lk
if bal<0:
continue
except ValueError:
print("Try again")
continue
else:
lockloop=False
lk=0
lock=0
print("Your balance is now: $", bal, sep='')
des=input("Would you like to (d)eposit, (w)ithdraw, (b)alance, or (e)nd? ")
witloop=True
deploop=True
lockloop=True
if lock>1 and bal>=0:
lock=1
if des=="deposit" or des=="d" and lock<4:
while deploop==True:
try:
dep=int(input("How much would you like to deposit? "))
if dep<=0:
print("Please input a positive amount")
continue
except ValueError:
print("Try again")
continue
else:
deploop=False
bal=dep+bal
dep=0
if bal<0 and lock==0:
bal=bal-50
lock=lock+1
print("You have incured an overdraft fee of $50. It will be removed from your account.")
if bal<0 and lock!=0:
lock=lock+1
print("Your account is still overdrawn. Please deposit funds.")
print("You now have: $", bal, sep='')
continue
elif des=="withdraw" or des=="w" and lock<4:
if bal<=0:
print("Cannot withdraw funds at this time.")
continue
while witloop==True:
try:
wit=int(input("How much would you like to withdraw? "))
if wit<=0:
print("Please input a positive amount")
continue
except ValueError:
print("Try again")
continue
else:
witloop=False
bal=bal-wit
wit=0
if bal<0 and lock==0:
bal=bal-50
lock=lock+1
print("You have incured an overdraft fee of $50. It will be removed from your account.")
if bal<0 and lock!=0:
lock=lock+1
print("Your account is still overdrawn. Please deposit funds.")
print("You now have: $", bal, sep='')
continue
elif des=="balance" or des=="b":
print("You have: $", bal, sep='')
continue
elif des=="end" or des=="e" and lock==0:
end=True
print("Thank you for banking with Nolan's Banking Services today! Have a great day! :)")
else:
print("You must enter one of the four options, try again")
continue
atm()

Running your code as-is is returning this error:
UnboundLocalError: local variable 'end' referenced before assignment
The reason here is to do with the scope of your variables. You are declaring the bal, lock and end variables outside of your function, therefore making them global variables. But you are also then declaring those variables inside the function, making them local variables. The interpreter is getting confused and the error is telling you the the local variable end is being used before it is being assigned.
Don't mix and match variables inside and outside a function like this. You should try to avoid global variables in your functions as much as possible as a good rule of thumb when programming.
You could read some more here as a starting point:
https://www.w3schools.com/python/python_variables_global.asp
https://bobbyhadz.com/blog/python-unboundlocalerror-local-variable-name-referenced-before-assignment
I don't know how to have the function use a different variable for each person
You can pass arguments into your function like this. In this case, when we define the function, we tell it to expect an argument called user that you can then use inside your function.
def atm(user):
if user == 'Nolan':
print('Hi Nolan')
elif user == 'Lummers':
print('Hi Lummers')
else:
print("I don't talk to strangers")
atm('Nolan')
atm('Lummers')
atm('John Doe')

To provide a different variable for each person I suggest you look into classes. Something like ...
class Person:
def __init__(self, name: str, balance: float = 0):
"""Create a new person each time."""
self.name = name
self.balance = balance
def action(self, action: str, amount: float):
if action == 'deposit':
self.balance += amount
elif action == 'withdraw':
self.balance -= amount
def __repr__(self):
return f"{self.name} {self.balance}"
def main():
customers = {}
customers['Fred'] = Person('Fred', 500)
customers['Jane'] = Person('Jane')
"""Preload some actions for example."""
actions = [
['Fred', 'withdraw', 123],
['Jane', 'deposit', 789]
]
"""Process the actions. Could run forever."""
for person, action, value in actions:
if person in customers:
customers[person].action(action, value)
print(customers)
if __name__ == '__main__':
main()

Related

Unit Test functions which include user input, while loops and whose input is another functions output - Python

I have made a program for an ATM machine, which checks the pin that a user inputs, allows the user to enter an amount to withdraw if the pin matches and then withdraws the money from the account_balance. However, each function is seemingly dependent: the return of one function is the parameter of another. This is confusing to test each function separately and when I try to do so, the whole program runs and asks for input from each function.
As my get_pin and get_amount function also have while loops with user input, I feel like this has added another complication to the way I need to unit test.
Is there a way to do this?
Or do you think it is best to refactor my code to remove user input and while loops and just have parameters in each individual function?
The test I would like to check would be:
withdraw_cash function - to check if the correct amount is withdrawn
get_pin function - check if the pin matches
get_amount function - check incorrect amount is added bringing up an error message.
My atm program is:
user = {
'pin': 1234
}
def withdraw_cash(amount):
balance_account = 100
if amount > balance_account:
raise ValueError("You don't have sufficient balance to make this withdrawal")
else:
new_balance = balance_account - amount
return new_balance
def get_pin():
count = 0
to_exit = False
while (count < 3) and (not to_exit):
try:
pin = int(input('Please enter your four digit pin: '))
except ValueError:
print("Please enter correct pin")
count += 1
if pin != user['pin']:
print("Pin does not match.. Try Again")
count += 1
else:
return get_amount(pin)
if count == 3:
a = '3 UNSUCCESFUL PIN ATTEMPTS, EXITING \n !!!!!YOUR CARD HAS BEEN LOCKED!!!!!'
return a
def get_amount(pin):
while True:
try:
amount = int(input("Enter the amount of money you want to withdraw: "))
except ValueError as v:
print(f"Enter correct amount: ")
else:
return withdraw_cash(amount)
try:
get_pin()
except ValueError as v:
print(f"ERROR: {v}")

How do I add an inventory remaining counter? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
Previously, I have asked for help in my attempt to add an inventory counter that has not worked. This is the original program I made. Everything works properly. How do I set each item (Pants, Shirt, Dress, Socks, and Sweater) to have a qty of 100 then take the input of qty and subtract that number. Lastly, printing what is left of the 100 after your bill is printed in Option 2 of the menu. Please edit the code to help me solve this issue. I really want to be done with this program. Thank you for your time.
#DEFINING EACH RETAIL ITEM TEMPLATE
class RetailItem:
def __init__(self,desc,unit,price):
self.description = desc
self.units = unit
self.price = price
#CREATING WHERE SELECTED ITEMS WITH RESIDE
class CashRegister:
def __init__(self):
self.shopping_list=[]
def purchase_item(self,retail):
#adding item to list
self.shopping_list.append(retail)
#CREATING PRICING / COST
def get_total(self):
total = 0
for i in self.shopping_list:
total+=(i.units*i.price)
return total
#HOW THE CHECKOUT WILL FORMAT/LOOK IN AFFECT ON OPTION 2 (CHECKOUT)
def show_items(self):
if not self.shopping_list:
return
print("{:<15}{:<25}{:<25}{:<10}".format(" "*9,"Description","Units","Price"))
print("-"*75)
for c,i in enumerate(self.shopping_list,1):
print("{:<15}{:<25}{:<25}{:<10}".format("Item #"+str(c),i.description,i.units,i.price))
print("-"*75)
def main():
#ADDING TO CART
c=CashRegister()
#MENU
while 1:
try:
print("1. Purchase\n2. Checkout\n3. Clear\n4. Exit")
print()
choice = int(input("Enter your choice: "))
print()
if choice == 1:
while 1:
print()
print("Menu\n-----------------------\n1. Pants\n2. Shirt\n3. Dress\n4. Socks\n5. Sweater")
item_type = int(input("Select item: "))
print()
qty=int(input("Enter quantity: "))
#ITEMS TO CHOOSE FROM AND ADD TO CART
if item_type == 1:
c.purchase_item(RetailItem("Pants",qty,44.95))
elif item_type == 2:
c.purchase_item(RetailItem("Shirt",qty,34.95))
elif item_type == 3:
c.purchase_item(RetailItem("Dress",qty,79.95))
elif item_type == 4:
c.purchase_item(RetailItem("Socks",qty,6.95))
elif item_type == 5:
c.purchase_item(RetailItem("Sweater",qty,24.95))
else:
#ERROR MESSAGE
print("Invalid item! try again")
print()
continue
print("Item added to list")
print()
break
elif choice == 2:
if not c.shopping_list:
#ERROR MESSAGE
print("Nothing to checkout!")
print()
continue
#DISPLAYING BILL
c.show_items()
print(" "*60+"Total: ${}".format(round(c.get_total(),2)))
print()
elif choice == 3:
#CLEARING
c.shopping_list=[]
elif choice == 4:
#EXIT
exit()
else:
#ERROR MESSAGE
print("Invalid choice! try again!")
print()
#ERROR MESSAGE
except Exception as e:
print("Invalid choice! try again!"+str(e))
print()
#RUN PROGRAM
if __name__ == "__main__":
main()
You never define item_type_qty. All you ever do with it in your class is this:
self.item_type_qty[["Pants",20],["Dress",20]]
Which has no effect, since it looks like you're trying to get a value out using weird indexes. If you meant to assign it, do it like this:
self.item_type_qty = [["Pants",20],["Dress",20]]
However, you'll run into another problem with this line:
for x in c.item_type_qty:
That line is run before you call inhand, meaning item_type_qty will be still undefined when that line is reached, throwing that error anyway. You kind of have a circular dependency going on, where you try to loop through item_type_qty, which is set by inhand(), but then in your loop you call inhand() with x[0] and x[1], but x is an item from item_type_qty, which is defined in inhand. Just kind of a messy situation that doesn't make sense.

Python not importing data structure [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I'm trying to create a text-based game. I've made a basic/generic intro and now it's getting long so I want to create a new file so that I can add things like armor and weapons. When I went to try to import 'my_character' it gave me an error so I went to research this problem and I found this, so I tried it. I just got an error message saying it wasn't define (similar to the error below). This is the intro part named intro:
# Date started: 3/13/2018
# Description: text based adventure game
import time
def display_intro():
print('It is the end of a 100 year war between good and evil that had\n' +
'killed more than 80% of the total human population. \n')
time.sleep(3)
print('The man who will soon be your father was a brave adventurer who \n'
+ 'fought for the good and was made famous for his heroism. \n')
time.sleep(3)
print('One day that brave adventurer meet a beautiful woman who he later \n'
+ 'wed and had you. \n')
time.sleep(3)
def main():
display_intro()
main()
gen = input('\nYour mother had a [Boy or Girl]: ')
name = input("\nAnd they named you: ")
print("You are a {} named {}".format(gen, name))
chara_class = None
# Assigning points Main
my_character = {
'name': name,
'gender': gen,
'class': chara_class,
'strength': 0,
'health': 0,
'wisdom': 0,
'dexterity': 0,
'points': 20
}
# This is a sequence establishes base stats.
def start_stat():
print("\nThis is the most important part of the intro")
time.sleep(3)
print("\nThis decides your future stats and potentially future gameplay.")
time.sleep(4)
print("\nYou have 20 points to put in any of the following category: Strength, Health, Wisdom, or Dexterity.\n"
)
def add_character_points(): # This adds player points in the beginnning
attribute = input("\nWhich attribute do you want to assign it to? ")
if attribute in my_character.keys():
amount = int(input("By how much? "))
if (amount > my_character['points']) or (my_character['points'] <= 0):
print("Not enough points!!! ")
else:
my_character[attribute] += amount
my_character['points'] -= amount
else:
print("That attribute doesn't exist! \nYou might have to type it in all lowercase letters!!!")
def remove_character_points():
attribute = input("\nWhich of the catagories do you want to remove from? ")
if attribute in my_character.keys():
amount = int(input("How many points do you want to remove? "))
if amount > my_character[attribute]:
print("\nYou are taking away too many points!")
else:
my_character[attribute] -= amount
my_character['points'] += amount
else:
print(
"That attribute doesn't exist! \nYou might have to type it in all lowercase letters!!!")
def print_character():
for attribute in my_character.keys():
print("{} : {}".format(attribute, my_character[attribute]))
playContinue = "no"
while playContinue == "no":
Continue = input("Are you sure you want to continue?\n")
if Continue == "yes" or "Yes" or "y":
playContinue = "yes"
start_stat()
add_character_points()
elif Continue == "n" or "No" or "no":
main()
running = True
while running:
print("\nYou have {} points left\n".format(my_character['points']))
print("1. Add points\n2. Remove points. \n3. See current attributes. \n4. Exit\n")
choice = input("Choice: ")
if choice == "1":
add_character_points()
elif choice == "2":
remove_character_points()
elif choice == "3":
print_character()
elif choice == "4":
running = False
else:
pass
def story_str():
print(
"\nYou were always a strong child who easily do physical labor and gain lots of muscle."
)
time.sleep(3)
print("\nYou regularly trained with your dad who was also a skilled swordsman.")
time.sleep(3)
print("\nAs you grew into an adult, you're swordsmanship improved drastically.")
time.sleep(3)
print("\nOnce old enough, you joined the local guild as a warrior.")
time.sleep(3)
def story_dex():
print("\nYou were a sly child. You would always be stealing from other people and with"
+ "\nconstant practice you became proficient at thieving.")
time.sleep(3)
print("\nCombined with the skill of knives and short-blades, you became an extremely deadly assassin."
)
time.sleep(3)
print("\nOnce old enough, you joined the local guild as an assassin.")
time.sleep(3)
def story_wis():
print("\nYou grew up as a very intellegent child. You read books everyday and realized that magic"
+ "is the best offensively and defensively.")
print("\nYou grew up and attended the best magic school avalible and graduated."
)
print("\nYou soon went to the local guild and joined as a wizard.")
run_story = False
while run_story:
if my_character['strength'] >= 13:
story_str()
chara_class = 'Warrior'
run_story = True
else:
continue
if my_character['dexterity'] >= 13:
story_dex()
chara_class = 'Assassin'
run_story = True
else:
continue
if my_character["wisdom"] >= 13:
story_wis()
chara_class = 'Mage'
run_story = True
else:
continue
The command I have typed on part1 is to try to import my_character is:
from intro import my_character
print(my_character)
I have been trying to import my_character but it comes up as:
Traceback (most recent call last):
File "C:/Users/user/Desktop/part1.py", line 5, in <module>
my_character
NameError: name 'my_character' is not defined
The original file was named "intro" and the new one is named "part1". Do I need to do the 'if name == "__main"' thing? If so, what does that do?
Check for:
1) is the file name my_character.py
2) you have imported it as my_character
3) my_character is in the main python directory (if you are importing in interpreter)

Looping functions together for an FSM

As many of you have probably seen and/or coded, I'm trying to make a finite state machine; 5 states and 9 transitions, to determine if someone is laughing. I don't necesarrily want the entire answer, cuz I do want to figure out as much as I can by myself. However, the professors and TA's aren't always very quick or helpful when answering, and this place is way more useful anyway.
I just want to be able to type "ha" or "ho" until a "!" is entered, saying "you laughed." Any other characters will end it. There are 3 functions to make; the get_ch(), the find_state(), and the main(), which drives both of the other ones. Here's what I have:
def get_ch(): # prompt for the input in a loop
ch = input("Enter a character or press the Return key to finish: ")
if len(ch) > 1:
print("Invalid input, please try again.")
else:
return ch
def find_state(state, ch):
if state==1:
if ch=="h" or ch=="H":
state=2
return state
else:
state=5
return state
if state==2:
if ch=="a" or ch=="A" or ch=="o" or ch=="O":
state=3
return state
else:
state=5
return state
if state==3:
if ch=="!":
state=4
return state
if ch=="h" or ch=="H":
state=2
return state
else:
state=5
return state
def main():
print("I can recognize if you are laughing or not.")
print("Please enter one character at a time.")
# initialize the variables, for example:
ch=get_ch()
string=""
state=1
#call the functions in a loop
while get_ch():
if len(ch)<1:
print("\nYou entered", string)
print("You are laughing.")
print("You are not laughing.")
else:
if state<4:
find_state(state,ch)
string+=ch
continue
if state==4:
print("\nYou entered", string)
print("You are laughing.")
else:
print("\nYou entered", string)
print("You are not laughing.")
main()
The issue I'm having is that the functions aren't "talking" to each other. I don't know if this is because they are not properly looped in the main() or if the issue lies within the individual functions themselves (such as calling back on get_ch() while in find_state()).

Function not calling properly

def main():
def load():
name=0
count=0
totalpr=0
name=input("Enter stock name OR -999 to Quit: ")
while name != '-999':
count=count+1
shares=int(input("Enter number of shares: "))
pp=float(input("Enter purchase price: "))
sp=float(input("Enter selling price: "))
commission=float(input("Enter commission: "))
name = input("Enter stock name OR -999 to Quit: ")
def calc():
amount_paid=shares*pp
commission_paid_purchase=amount_paid*commission
amount_sold=shares*sp
commission_paid_sale=amount_sold*commission
profit_loss=(amount_sold - commission_paid_sale) -(amount_paid + commission_paid_purchase)
totalpr=totalpr+profit_loss
def print():
print("\nStock Name:", name)
print("Amount paid for the stock: $", format(amount_paid, '10,.2f'))
print("Commission paid on the purchase: $", format(commission_paid_purchase, '10,.2f'))
print("Amount the stock sold for: $", format(amount_sold, '10,.2f'))
print("Commission paid on the sale: $", format(commission_paid_sale, '10,.2f'))
print("Profit (or loss if negative): $", format(profit_loss, '10,.2f'))
print("Total Profit is $", format(totalpr, '10,.2f'))
return main()
load() #to input the values
calc()
print()
I'm not sure what I'm doing wrong:
Should I be putting in variable names into def load():, def calc(): and def print():?
As I run it now, it says "load" is not defined. How would I go about defining load? And for that matter, if I didn't define def calc(): and def print(): how do I define those?
I do properly call them at the end of the code, in the order that I'd like to call them -- load, calc, and then print.
Is my "return main()" the right thing to do? I don't know, I Just want this code to run properly without error that's all. I'm under the impression that I'm just missing a few things. Any help would be appreciated.
You are defining load() inside the scope of main(). This means you cannot use the function outside of main().
The easy solution is that you should put your function defines for load, calc, and print outside of the definition of main() (btw, call it something else like print_stock info, print is already a function!)
You also do not need to return main(). I am unsure what you are trying to do, but it is not necessary at all.
yikes.
your first mistake: calling a function in another function. Maybe you meant to do
class Main:
def load(self):
#do a thing
then you'd have to do
main = Main()
main.load()
your second mistake was defining a new a print() function that uses print functions, as one already exists. Rename it, as that will cause a huge error
This is a minimal working example to illustrate how one can solve what you are trying to do.
# helper for interpreting input
import ast
#: initial starting values
thing, count, cost, total = 'Nothing', 0, 0, 0
# define all functions at module indentation
def get_user_input():
global thing, count, cost # write to the GLOBAL names thing, count and cost
thing = input('What have you?') # ask for a string
count = ast.literal_eval(input('How much do you have?')) # ask for a string and interpret it: "3.2" => float
cost = ast.literal_eval(input('How much does each cost?'))
def compute():
global total # write to global name total
total = count * cost # can read from global names
def pretty_print(): # not named print! we still need print to print!
print("You have", count, thing)
print("At", cost, "each, that makes", total, "in total")
# call functions at module indentation
get_user_input() # ducks, 3, 42
compute()
pretty_print()
# You have 3 ducks
# At 42 each, that makes 126 in total
One thing to warn you about: working with global variables is generally a bad idea. For a small script it's fine, but you've already messed up the basics - globals are tricky, so avoid them whenever possible. If you just want to run these commands, do not write them as functions, execute them directly. Basically, leave away the def ... and global ... lines and put everything on the same indentation, then remove the last three lines.
If you really want to store and print multiple things, you need to use containers. Just assigning to a value in a loop, e.g. thing = input('What have you?'), will leave it at the last value entered. Instead, you need a container like a list. You can then append additional values to it.
container = [] # [] is a list literal
for _ in range(3): # non-infinite loop
next_thing = ast.literal_eval(input('Place your order...\n'))
container.append(next_thing)
print("You ordered", container)
def load():
global name
global count
global shares
global pp
global sp
global commission
name=input("Enter stock name OR -999 to Quit: ")
count =0
while name != '-999':
count=count+1
shares=int(input("Enter number of shares: "))
pp=float(input("Enter purchase price: "))
sp=float(input("Enter selling price: "))
commission=float(input("Enter commission: "))
calc()
display()
name=input("\nEnter stock name OR -999 to Quit: ")
def calc():
global amount_paid
global amount_sold
global profit_loss
global commission_paid_sale
global commission_paid_purchase
global totalpr
totalpr=0
amount_paid=shares*pp
commission_paid_purchase=amount_paid*commission
amount_sold=shares*sp
commission_paid_sale=amount_sold*commission
profit_loss=(amount_sold - commission_paid_sale) -(amount_paid + commission_paid_purchase)
totalpr=totalpr+profit_loss
def display():
print("\nStock Name:", name)
print("Amount paid for the stock: $", format(amount_paid, '10,.2f'))
print("Commission paid on the purchase: $", format(commission_paid_purchase, '10,.2f'))
print("Amount the stock sold for: $", format(amount_sold, '10,.2f'))
print("Commission paid on the sale: $", format(commission_paid_sale, '10,.2f'))
print("Profit (or loss if negative): $", format(profit_loss, '10,.2f'))
def main():
load()
main()
print("\nTotal Profit is $", format(totalpr, '10,.2f'))

Categories

Resources