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,151
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,220
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,950
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,220
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,220
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.
Posts: 4
Threads: 0
Joined: Mar 2024
Jun-03-2024, 02:46 PM
(This post was last modified: Jun-03-2024, 08:14 PM by Gribouillis.)
(Apr-12-2019, 10:48 AM)ichabod801 Wrote: (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 Link Removed money on telegram[/url] 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.
If you’re working with multiple functions that modify the money variable, constantly reassigning money after each function call is necessary to ensure clarity. This way, it's evident that each function call modifies the money variable, making it easier to track changes and debug any issues.
This approach explicitly shows that money is being passed through each function and modified accordingly. It prevents any ambiguity regarding which variables are being altered within each function.
However, if you find yourself needing to create hundreds of such functions, the issue lies not in the need to reassign values but in the design itself. In such cases, a more scalable and maintainable approach would be to create a generic function to handle these operations. This can significantly reduce redundancy and improve readability.
For instance, you could create a generic transaction function that takes the money variable and a function (e.g., old_witch, blacksmith) as arguments.
Even better, consider adopting Object-Oriented Programming (OOP) principles, especially if your game logic becomes more complex. You can encapsulate the money variable within a Player class and define methods for various transactions.
|