Python, Functions changing values - python

So I am having trouble getting this system to work, and I can't be sure that I'm asking the right question, but here is what is happening and what I want to happen.
money = 1
def Stats():
print
print "money " + str(money)
def gainM():
money + 2
Stats()
if money == 1:
gainM()
Now what happens when it goes to print money, the value is still 1 even though I add 2 to the value. (code is not a copy of my actual program, but an example to show what is happening.)

money + 2 is a no-op. You actually have to assign money to a new value
money = money + 2
# or
money += 2
But then you'll find you get an error - you can't assign to variables outside a function scope. You can use the global keyword:
global money
money += 2
This will allow you to change the value of money within the function.
However, the recommended way is passing money as a parameter:
def gainM(money):
money += 2
Stats()
return money
if money == 1:
money = gainM(money)
If you're using the second option (which you should be), you also need to change your Stats function, to have a money parameter as well.
def Stats(money):
print
print "money " + str(money)
Otherwise the function will print 1 instead of 3.
Another recommendation - use string formatting.
'money %d' % money # the old way
'money {}'.format(money) # the new and recommended way
Now you pass money into the Stats function.
def gainM(money):
money += 2
Stats(money)
return money

You need to assign the new value to money. Like so:
money = money + 2
Or the shorthand form:
money += 2
Also, if the variable is outside your function, you need to declare it global(so it doesn't instead create a local variable)
So you end up with:
def gainM():
global money
money += 2
Stats()
Edit: just to clarify, I'm not saying you should use global variables. In general they are a bad idea(though they may be useful in some situations). However, that's what this particular example needs to work. Chances are, however, that what you want is probably a class with instance variables that the methods of that class modify. However, given that you don't seem to have grasped the basics of the language yet, take things one step at a time and don't worry about any words in my previous sentences you didn't understand for now :)

Related

dont know how to update score in python

So I'm in an intro to programming class and I need help updating the score in my "text based adventure game". What happens is you press enter, then a text appears (ex, you walk to the plane to find a monkey), then it says "Your score is 5". I want it so every time I press enter, the text appears and then my score goes up by 5. I spent a couple hours reading through my textbook and I don't know what to do. Everything is fine except the showScore function since it keeps printing my score as 5 after every step.
This is an example of the code:
def promptUser():
input("\n<Press Enter to continue...>\n")
def base():
print("You approach the base with friends")
def showScore():
x = 0
score = x + 5
print("Your score is now" ,score,)
I'm not a python programmer but I came across you post while doing some peer review for first timers questions and I thought I could help. Global Variables is what will solve your issue and based on this Python Global Variabl explaination the following should work for you.
score = 0
def promptUser():
input("\n<Press Enter to continue...>\n")
def shelter():
print("You approach the base with friends")
def showScore():
score = score + 5
print("Your score is now" ,score)
Currently you are defining your the variable 'x' within the showScore() function which means each time you call that function you are resetting x to zero before you add 5. In my solution, I define score as a Global variable so that each time you call the showScore() function it accepts simply adds 5 to score and then saves that in memory as the new score before displaying the score.
This may work for your current problem but in the real world it would be better to have a function that is dedicated to changing the score that is separate from the function that displays the score.
Hope this helps.
Try using:
def showScore():
score = 0
score = score + 5
print('Your score is now',score)
did you try putting score = 0 before the function then putting global score before score = score +5?

Python - Passing variables through functions

I am about a week into Python. I have looked at various other questions regarding this, and have grown fairly frustrated that my attempts to implement those suggestions are falling flat.
I have tried a few means of passing variables through, based on things I have read. For example (this isn't necessarily representative of a coherent attempt... I have tried many variations and have had to walk back to get code worth posting):
def verify_nums():
globhours = hours
globrate = rate
try:
globhours = float(globhours)
globrate = float(globrate)
return globhours,globrate
except:
print("You must provide numbers")
def calc():
globhours = globhours
globrate = globrate
if globhours > 40:
base = 40 * globrate
ot = (globhours - 40) * (globrate * 1.5)
pay = base + ot
print(pay)
else:
pay = globrate * globhours
print(pay)
hours = input("Enter hours worked: ")
rate = input("Enter hourly rate: ")
verify_nums()
calc()
I am supremely confused on how to transfer the hours and rate variables over to the calc() function.
I eventually figured out I could just merge these into one function...
def paycalc(hours,rate):
etc.
etc.
hours = input("Enter hours: ")
hours = input("Enter hours: ")
paycalc(hours,rate)
But for the sake of learning, I really want to get this global/local thing figured out.
Thanks for the help!
You seem to be trying to get Python to guess which functions are supposed to be global and which local based on their names. Python doesn't do that. If you assign to a variable in a function, and you want that assignment to be global, you need a global statement at the top of the function:
def verify_nums():
global globhours
global blograte
globhours = hours
globrate = rate
# ...
Also, globhours = globhours doesn't do anything useful—and, in fact, it causes a problem. If you global globhours in that function as well, the statement is meaningless. Without that, you're creating a local variable, and assigning it… the value of that local variable that doesn't exist yet.
Anyway, if you add the right global declarations to all of your functions, they will work, but it won't be a great design.
You really don't need any global variables here. If you think about values rather than variables, everything gets a lot easier.
Your verify_nums function needs to work on two values. So just pass those values in as parameters. And it needs to return two values—that's easy, you already did that part.
Now the caller has to store those two values that it returned, so it can pass them to the calc function. Which can also take two values as parameters.
Putting that all together:
def verify_nums(hours, rate):
try:
numhours = float(hours)
numrate = float(rate)
return numhours, numrate
except:
print("You must provide numbers")
def calc(hours, rate):
if hours > 40:
base = 40 * rate
ot = (hours - 40) * (rate * 1.5)
pay = base + ot
print(pay)
else:
pay = rate * hours
print(pay)
globhours = input("Enter hours worked: ")
globrate = input("Enter hourly rate: ")
hours, rate = verify_nums(globhours, globrate)
calc(hours, rate)
One problem left: what happens if there's an error with the user's input? Inside verify_nums, you handle the error with an except:, then you print a message and do nothing. That means you return None. So, when the caller tries to do hours, rate = None, it's going to get an error, which you're not handling. And you can't just carry on without values. What can you do?
More generally "return a pair of numbers, or return None" is a confusing contract for a function to fulfill. How do you use that function? With a whole lot of ugly type-checking. But "return a pair of numbers, or raise an exception" is a perfectly good contract. How do you use that function? With a simple try.
That's why it's better to put the exception handling in exactly the right place where you can deal with it. You want to skip calling calc if there's an error, so the except has to be where you call calc.
def verify_nums(hours, rate):
numhours = float(hours)
numrate = float(rate)
return numhours, numrate
def calc(hours, rate):
if hours > 40:
base = 40 * rate
ot = (hours - 40) * (rate * 1.5)
pay = base + ot
print(pay)
else:
pay = rate * hours
print(pay)
try:
globhours = input("Enter hours worked: ")
globrate = input("Enter hourly rate: ")
hours, rate = verify_nums(globhours, globrate)
except ValueError:
print("You must provide numbers")
else:
calc(hours, rate)
Another improvement you might want to consider: Have calc return the pay, instead of printing it, and make the caller print the value it returns.

Variables don't change after being run through a function

I'm writing a small game in python in which certain events happen and effect variables which need to stay in certain parameters. I have the main file and then another file which has all of the events in them. Some of the values are changed in the function then supposed to change the overall values in main (Sorry if that doesnt make sense)
Here's the part in main:
while (army > -100 and army < 100 and people > -100 and people < 100 and church > -100 and church < 100 and affairs > -100 and money < 100 and money > -100):
os.system('clear')
#Top Bar. Should Stay throughout game.
print("[-]==[King: " + king + "]==[Years in power:" + str(years) +"]==[Army: " + str(army) + "]==[People: " + str(people) + "]==[Church: " + str(church) + "]==[Foreign Affairs: " + str(affairs) + "]==[Economy: " + str(money) +"]==[-]")
print(people)
event1(army, people, church, affairs, money, years)
That loops until one of the parameters falls below 0 then there's losing conditions
Right now there is only one event, and it's not quite finished, but I only need one thing to at least see a change in the values.
Here that:
def event1(army, people, church, affairs, money, years):
#Feilds are Flooding
print("")
print("Sire! The Feilds in the eastern baronies are flooding! What should we do?")
print("")
print("Choices:")
print("1: The rain will pass, do nothing. (~Money, People)")
print("2: Have the Royal Builders build flood protection! (~Money, People)")
print("")
c=input("Your choice sire: ")
while True:
if c > 2:
print("")
print("Please chose a valid option")
print("Your choice sire: ")
continue
if c == 1:
time.sleep(2)
print("")
print("You do nothing, your people starve from flooded feilds (-People, +Money)")
money = money+20
people = people-20
years = years+1
raw_input("Press Enter to go to the next year")
return money
return years
return people
break
After it runs the event the values people, money and years are all supposed to change, but when it loops, nothing changes.
Any help is appreciated! Thank you!
Those are local variables. As soon as you leave the method scope, the value is lost, unless you return and actually use the returned values.
In your caller, assign your variables with the new returned values:
money, years, people = event1(army, people, church, affairs, money, years)
and in event1, perform only one return (others are unreachable) of the tuple containing the 3 values you want to return (which is unpacked to the 3 upper level eponymous variables):
return money, years, people
YOU DO NOT NEED THE RETURN!!!!!!!!!!!!!!!!!!!! COMPLETELY REMOVE IT! READ THIS! (should help)
The return in fact ruins your command, and there is a really easily explainable way to understand how it works.
First I need to explain something, because I am kind of confused about your code. Return is used to make the value of your command whatever you have returned. Return is used like this:
def AddThreethousandTwohundredSeventyNineToNum(num):
num = num + 3279
return num
and then
print AddThreethousandTwohundredSeventyNineToNum(4)
It should print "3283". (3279 + 4)
print printThreethousandTwohundredSeventyNineToNum(2)
It will print "3281".
You can also do cool things like:
if AddThreethousandTwohundredSeventyNineToNum(x) == y:
DoSomething
All return does is make the value OF THE FUNCTION whatever you want it to be. In the last code, the function looks for what I made num, and sees that it is 4 or 2, so it does num = num + 3279, so num gets increased by 3279 (3273 or 3271). When you do return num, it makes THE FUNCTION equal num.
That means what you have done is changed all those beatiful values in lines 21-23 (money, people, etc.) and technically that is all you had to do. However, when you returned the numbers, you made your command not only change those values, but also become a number, and obviously you cant just have a number lying around in your command. Or else the interpreter will not understand.
I hope I was clear enough, and if not, please please PLEASE tell me (please).

Why do I get an UnboundLocalError in my function?

I am newbie, trying to learn python.
According to this article http://www.tutorialspoint.com/python/python_modules.htm, I get an UnboundLocalError in the following code but I don't understand why:
Money = 2000
def AddMoney():
# Uncomment the following line to fix the code:
# global Money
Money = Money + 1
print Money
AddMoney()
print Money
But the below code works fine
Money = 2000
def AddMoney():
# Uncomment the following line to fix the code:
# global Money
Money = 1
print Money //2000
AddMoney()
print Money //2000
They explain things in the article, but I'm still not sure that I understand. Why do I get an UnboundLocalError in the first example, but not in the second?
As you've mentioned, the article does explain a little bit, but not very much about why.
When you're programming and you write the name of something, the computer has to know where to go look for that thing. The where is a term known as scope. All variables in Python have a scope. Here are some examples to illustrate:
from __future__ import print_function
value = 'blue'
def fun():
value = 'yellow'
print("Value in function: ", value)
print("Value before: ", value)
fun()
print("Value after: ", value)
# Output:
#
# Value before: blue
# Value in function: yellow
# Value after: blue
In this script you define value to be 'blue'. Then inside the function you set it to 'yellow'. But why does it not stay 'yellow' after the function is called? Scoping.
When you define value = 'yellow' in your function, the name value is bound to 'yellow' only inside the current block (a function, in this case). You'll hear the terms shadow or hiding to explain what's happening here, because that's effectively what's happening. You are hiding the original value with a new value, but once your function ends, so does your new value.
You can see this by using the globals()and locals() builtins
from __future__ import print_function
from pprint import pprint
value = 'blue'
def fun():
print("Globals in function: ")
pprint(globals())
print("Locals in function: ")
pprint(locals())
value = 'yellow'
print("Value in function: ", value)
print("Globals at end of function: ")
pprint(globals())
print("Locals at end of function: ")
pprint(locals())
print("Globals before function: ")
pprint(globals())
print("Locals before function: ")
pprint(locals())
print("Value before: ", value)
fun()
print("Value after: ", value)
print("Globals after function: ")
pprint(globals())
print("Locals after function: ")
pprint(locals())
Now, python has a global keyword that allows you to tell Python that instead of looking inside the local scope, you want to look in the global scope for these variables:
from __future__ import print_function
value = 'blue'
def fun():
global value
value = 'yellow'
print("Value in function: ", value)
print("Value before: ", value)
fun()
print("Value after: ", value)
# Output:
#
# Value before: blue
# Value in function: yellow
# Value after: yellow
In Python, it will try to resolve names first in the local scope, and then in the global scope, which means you can write something like this:
from __future__ import print_function
value = 'blue'
def fun():
print("Value in function: ", value)
print("Value before: ", value)
fun()
print("Value after: ", value)
# Output:
#
# Value before: blue
# Value in function: blue
# Value after: blue
But if that works, then why doesn't your first example, with Money = Money + 1? The answer is simple, though perhaps unexpected:
Because you are trying to redefine Money in your function (the Money = part), it cannot go look for your variable in the global scope, because it doesn't know if you meant to use the global version or the local version, and you get an UnboundLocalError. So you need to tell Python what you mean: Did you want to use the global version, or should you be using something locally?
By declaring global Money, you tell Python explicitly that you want to use the global version. But if you want to use something local then you'll need to use a different name, or define Money before you try to use it as in Money + 1.
AddMoney doesnt know Money variable has been defined before so it crashes with local variable 'Money' referenced before assignment thinking is a local variable which should have been declared inside AddMoney class.
If you uncomment the global Money line inside AddMoney class it will work.
Also the second example is working because in the line Money = 1 you are not using Money variable, you are just asigning a value to Money and overriding the global value
Preface: I'm going with the assumption that the space before Money = 2000 in the second snippet is a mistake, because whitespace is significant in Python, but I don't think it actually makes a change here.
In your first example Money = Money + 1 is trying to read from a variable and then assign a new value to it. Money doesn't exist in the local scope, so it throws an error. The second example is only assigning a value to a variable. AddMoney() creates a local variable called Money and then does nothing with it. The Money from the outer scope is unchanged, as your comments indicate.
The reason is the conflict between globals and local scope variables
(As others have said)
declaring money as global in the function shall do good
Money = 2000
def AddMoney():
global Money
Money = Money + 1
In both functions, you need to delete the hashtag in the line '# global Money' in order for the function to work properly. Hashtags in Python cause the rest of the line to be 'commented', which are lines that will not affect your code and instead act as notes to the developer.
This code will work properly:
Money = 2000
def AddMoney():
# Uncomment the following line to fix the code:
global Money
Money = Money + 1
print Money
AddMoney()
print Money
In your second piece of code, the function isn't redefining the variable money outside of the function's environment, so while an error is not appearing, you are not accomplishing what you want with the code. Again, deleting the hashtag (uncommenting) will solve your problem. This code will work:
Money = 2000
def AddMoney():
# Uncomment the following line to fix the code:
global Money
Money = 1
print Money //2000
AddMoney()
print Money //2000
Hope this helps!

Pokemon Battle in Python [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 9 years ago.
Improve this question
I am not that great with OOP but I am stuck right now. First off, I don't think I set the damage correctly and I am trying to figure out how to output the damage to the user. Any help would be appreciated.
#Pokemon Battle
import random
from time import sleep
from array import *
class Pokemon(object):
def __init__(self, xname, xhealth):
self.name = xname
self.health = xhealth
def damage1(self,Charmander):
Squirtle.health - self.damage
def damage2(self,Charmander):
self.health - Squirtle.damage
print ('What is your name?')
name = input()
print ('Hello '+name+'! You are about to enter a pokemon battle.')
sleep(1)
print ('A wild Charmander appeared!')
sleep(1)
print ('You sent out Squirtle!')
sleep(1)
print ('Do you want to fight(1) or run away(2)?')
choice = input()
damage = random.randint(1,50)
damage = str(damage)
if choice == '1':
print ('You dealt '
sleep(1)
print ('Charmander did ')
if choice == '2':
print ('You ran away.')
else:
print ('Not a valid response.')
Right off the bat, you can use String Formatting to insert variables in strings.
#old way
some_string = "the value of 2+2 = %i",4
#new way
some_string = "the value of 2+2 = {}".format(4)
For your code, try:
if choice == '1':
print("You dealt {}".format(damage_goes_here))
However there's deeper issues with your code. Let me look more and I'll edit.
Object Oriented Programming
Okay so the first problem you have is that you never actually MAKE anything. When you write class SomeClassLikePokemonOrWhatever: what you're doing is making a template of something. It's like making a cast or a mold of an item before you make it -- you want all your Pokemon (or whatever) to be alike, so you make a mold of them and cast them all from the same mold. You can decorate and unique-ify them after that, but we want them all to be the same, basically. So instead, you should have something like this:
class Pokemon:
def __init__(self,name,base_hp):
self.name = name
self.base_hp = base_hp
#the __init__ function gets called when you "instantiate" (e.g. actually MAKE)
#whatever object the class is describing. In most cases, all it does it set
#the starting properties of the object based on how you define it (like this)
#you could also say all pokemon are beautiful, and add something like
self.description = "Absolutely GORGEOUS darling!"
#that will be constant for every pokemon you make through this definition.
#you said you wanted damage to be random between 1-50, so we don't need to add
#that statistic to the class.
That covers the definition of the object, but it still doesn't DO anything. In fact, let's let it do something, shall we? We want it to attack. What's a pokemon that doesn't fight? So let's give it a function (in a class, we call functions "methods.")
def attack(self,target):
#in this method we'll teach the pokemon how to fight
damage = random.randint(1,50) #don't forget to import random to do this
target.hp -= damage
Now you need to make some stuff. You defined what a Pokemon is and what it can do, but you haven't made one. Let's make some. Luckily it's easy.
my_awesome_pokemon = Pokemon("Charizard",200) #you give the args in the same order __init__ takes them
your_sucky_pokemon = Pokemon("Magikarp",20) #same deal here.
That makes two pokemon, one for you and one for them. If you wanted a whole belt full, you could define an array all_my_pokemon and fill it with Pokemon objects defined in this way. Just something to think about.
To actually fight, you'd tell your pokemon to attack.
my_awesome_pokemon.attack(your_sucky_pokemon)
#just that easy, now display how much damage it did....WAIT STOP WE HAVE A PROBLEM!
since you want random damage every time, you can't access it with something like my_awesome_pokemon.damage, since it's a local variable it dies when the attack method ends. You can, however, return that value in the method and use that.... Let's change our method.
def attack(self,target):
damage = random.randint(1,50)
target.hp -= damage
return damage #now we have some way to access how much damage was done from our main thread
Now to display it, we can do
damage_done = my_awesome_pokemon.attack(your_sucky_pokemon) #since .attack() returns the damage it deals, this sets damage_done to a sane amount.
print("My pokemon {} dealt {} damage to {}".format(my_awesome_pokemon.name,damage_done,your_sucky_pokemon.name))
Does that make sense?
I really think you should brush up on your OOP and then come back to this problem, because this is definitely a decent problem to practice on.
First of all, you set damage, and then set it again randomly:
self.damage = xdamage
self.damage = random.randint(1,50)
And this function is left open, which is going to cause compile issues, besides for the fact that you're missing any actual data!
print ('You dealt '
sleep(1)
print ('Charmander did ')
You're going to want to call your damage variable and Charmander's damage variable; think about how that is accomplished in OOP.

Categories