Posts: 1
Threads: 1
Joined: Apr 2019
As my last assignment in class I’m making a sort of fantasy marketplace RPG simulation where I have a money value that needs to change and use the new value no matter which function the user chooses to run first. My program is very long so I’ve shortened it and used the main parts of the problem I’m trying to solve.
money = 4000
def blacksmith():
price1 = 300
global money
money = 4000
money -= price1
print (“You bought a sword”)
def oldwitch():
price2 = 700
global money
money = 4000
money -= price2
print (“You bought a potion”)
def moneyval():
print (“You have”, money, “in your bag”)
finished = False
while (finished = False):
print (“1. Blacksmith”)
print (“2. Old Witch”)
print (“3. Check money”)
choice = int(input(“Type the number of the person you want to talk to first”))
if (choice == 1):
blacksmith()
elif (choice == 2):
oldwitch()
elif (choice == 3):
moneyval() So I have a few scenarios that occur when running the program.
Scenario 1:
I run moneyval() and it prints that I have 4000. Then I run blacksmith() and after that runs I choose moneyval() again and it prints that I have 3700. All good
Scenario 2:
I run moneyval() and it prints that I have 4000. Then I run oldwitch() and after that runs I choose moneyval() again and it prints that I have 3300. All good
Scenario 3:
I run moneyval() and it prints that I have 4000. Then I run blacksmith() and after that runs I choose moneyval() again and it prints that I have 3700. Then I run oldwitch() and choose moneyval() after and it prints that I have 3300, which is incorrect and I should have 3000.
I know that using “global money” and then setting “money = 4000” on each function resets its value to 4000 so I was wondering if there’s a way to have it so that no matter which function runs first, the money value can change and use it’s new value for the rest of the program. For example if I want to run blacksmith() first and then oldwitch(), moneyval() should print to 3000. And if I want to run oldwitch() first and then blacksmith(), moneyval() should still print to 3000.
Posts: 5,150
Threads: 396
Joined: Sep 2016
Apr-11-2019, 08:03 PM
(This post was last modified: Apr-11-2019, 08:03 PM by metulburr.)
(Apr-11-2019, 07:46 PM)saturnstars Wrote: I know that using “global money” and then setting “money = 4000” on each function resets its value to 4000 so I was wondering if there’s a way to have it so that no matter which function runs first, the money value can change and use it’s new value for the rest of the program. For example if I want to run blacksmith() first and then oldwitch(), moneyval() should print to 3000. And if I want to run oldwitch() first and then blacksmith(), moneyval() should still print to 3000. That is why because you are resetting your value back to 4000 every time. Just comment out the money = 4000 on each function and the global variable will be deducted from either function.
money = 4000
def blacksmith():
price1 = 300
global money
#money = 4000
money -= price1
print ("You bought a sword")
def oldwitch():
price2 = 700
global money
#money = 4000
money -= price2
print ("You bought a potion")
def moneyval():
print ("You have”, {}, “in your bag".format(money))
finished = False
while (finished == False):
print ("1. Blacksmith")
print ("2. Old Witch")
print ("3. Check money")
choice = int(input("Type the number of the person you want to talk to first"))
if (choice == 1):
blacksmith()
elif (choice == 2):
oldwitch()
elif (choice == 3):
moneyval()
moneyval()
Recommended Tutorials:
Posts: 13
Threads: 0
Joined: Mar 2019
Just declare money as a global inside your functions that way when the rest of the code runs it knows that when you reference money, you're referencing the global variable.
Posts: 4,229
Threads: 97
Joined: Sep 2016
Or even better, don't use a global. Pass money as a parameter, return it, and assign it. For example:
def oldwitch(money):
print ("You bought a potion")
return money - 700 And then call it with an assignment: money = oldwitch(money) .
Posts: 13
Threads: 0
Joined: Mar 2019
Apr-11-2019, 09:33 PM
(This post was last modified: Apr-11-2019, 09:35 PM by loomski.)
(Apr-11-2019, 09:06 PM)ichabod801 Wrote: Or even better, don't use a global. Pass money as a parameter, return it, and assign it. For example: def oldwitch(money): print ("You bought a potion") return money - 700 And then call it with an assignment: money = oldwitch(money) .
The problem with that is he is still declaring a variable money = 4000 so look at the result of this:
def oldwitch(money):
print("You bought a potion")
return money - 700
money = 4000
print(money)
print(oldwitch(money))
print(money) The result will be
>>> print(money)
4000
>>> print(oldwitch(money))
You bought a potion
3300
>>> print(money)
4000 Edit: I see you said he should assign money to old_witch(money) and that would work, but is this the best approach?
Posts: 1,936
Threads: 8
Joined: Jun 2018
Another way is to use closure 'creatively' to reference the money (not that I recommend such a practice; changing value in global namespace from within function makes debugging real pain):
>>> money = [4000]
>>> def blacksmith():
... money[0] -= 300
... print('you bought a sword')
...
>>> def oldwitch():
... money[0] -= 700
... print('you bought a potion')
...
>>> blacksmith()
you bought a sword
>>> money[0]
3700
>>> oldwitch()
you bought a potion
>>> money[0]
3000
I'm not 'in'-sane. Indeed, I am so far 'out' of sane that you appear a tiny blip on the distant coast of sanity. Bucky Katt, Get Fuzzy
Da Bishop: There's a dead bishop on the landing. I don't know who keeps bringing them in here. ....but society is to blame.
Posts: 4,229
Threads: 97
Joined: Sep 2016
(Apr-11-2019, 09:33 PM)loomski Wrote: I see you said he should assign money to old_witch(money) and that would work, but is this the best approach?
Yes.
Posts: 13
Threads: 0
Joined: Mar 2019
(Apr-11-2019, 10:07 PM)ichabod801 Wrote: (Apr-11-2019, 09:33 PM)loomski Wrote: I see you said he should assign money to old_witch(money) and that would work, but is this the best approach? Yes.
But then he will have to keep doing money = old_witch(money) and after that, money = blacksmith(money) and then every single time he wants to make a new function where he adds money or decrements money he will have to keep reassigning?
I don't know, maybe for this particular thing where he's just calling 2 functions and checking them maybe this might be the "best" way (lol) but if he wants to have a hundred of those types of functions, I don't know.
Posts: 4,229
Threads: 97
Joined: Sep 2016
(Apr-12-2019, 12:59 AM)loomski Wrote: But then he will have to keep doing money = old_witch(money) and after that, money = blacksmith(money) and then every single time he wants to make a new function where he adds money or decrements money he will have to keep reassigning?
Yes, which will make it clear that money is being modified by that function call. If he's just got a bunch of oldwitch() and blacksmith(), it is not clear at all that money is used or modified by those functions. And when he runs into a bug with money changing or not changing as expected, it's going to be that much harder track down the bug and figure it out.
(Apr-12-2019, 12:59 AM)loomski Wrote: I don't know, maybe for this particular thing where he's just calling 2 functions and checking them maybe this might be the "best" way (lol) but if he wants to have a hundred of those types of functions, I don't know.
If he wants to have hundreds of these types of functions, then the hundreds of functions are a problem, not having to pass, return, and assign values. At that point he needs a generic function for handling purchases, and he needs to move the distinction between witches and blacksmiths into some data. At that point he should also switch to OOP, and money should become an attribute of the Player class, which is in turn an attribute of the Game class.
|