Beginner trying to understand functions.

S

simonh

In my attempt to learn Python I'm writing a small (useless) program to
help me understand the various concepts. I'm going to add to this as I
learn to serve as a single place to see how something works,
hopefully. Here is the first approach:



name = input('Please enter your name: ')
print('Hello', name)

while True:
try:
age = int(input('Please enter your age: '))
break
except ValueError:
print('That was not a valid number. Please try again.')

permitted = list(range(18, 31))

if age in permitted:
print('Come on in!')
elif age < min(permitted):
print('Sorry, too young.')
elif age > max(permitted):
print('Sorry, too old.')

input('Press any key to exit.')



That works fine. Then I've tried to use functions instead. The first
two work fine, the third fails:



def getName():
name = input('Please enter your name: ')
print('Hello', name)

def getAge():
while True:
try:
age = int(input('Please enter your age: '))
break
except ValueError:
print('That was not a valid number. Please try again.')

def checkAge():
permitted = list(range(18, 31))
if age in permitted:
print('Come on in!')
elif age < min(permitted):
print('Sorry, too young.')
elif age > max(permitted):
print('Sorry, too old.')

getName()
getAge()
checkAge()

I get this error message: NameError: global name 'age' is not
defined.

I'm stuck, can someone help? Thanks.
 
J

James Mills

That works fine. Then I've tried to use functions instead. The first
two work fine, the third fails:

[ ... snip ... ]

Try this:

def getName():
name = input('Please enter your name: ')
print('Hello', name)
return name

def getAge():
while True:
try:
return int(input('Please enter your age: '))
except ValueError:
print('That was not a valid number. Please try again.')

def checkAge(age):
permitted = list(range(18, 31))
if age in permitted:
print('Come on in!')
return True
elif age < min(permitted):
print('Sorry, too young.')
elif age > max(permitted):
print('Sorry, too old.')

return False

name = getName()
age = getAge()
if checkAge(age):
# Do something
else:
# Do something else


cheers
James

PS: Read the Tutorial :)
 
P

Pierre-Alain Dorange

simonh said:
def getName():
name = input('Please enter your name: ')
print('Hello', name)

def getAge():
while True:
try:
age = int(input('Please enter your age: '))
break
except ValueError:
print('That was not a valid number. Please try again.')

def checkAge():
permitted = list(range(18, 31))
if age in permitted:
print('Come on in!')
elif age < min(permitted):
print('Sorry, too young.')
elif age > max(permitted):
print('Sorry, too old.')

getName()
getAge()
checkAge()

I get this error message: NameError: global name 'age' is not
defined.

Indeed age was not a global... So :

1/ make it a global (just define "age=0" before getAge()

2/ or return a value from getAge() and pass this avlue to checkAge.

I recommand the second option, less globals is always better.

def getAge():
while True:
try:
age = int(input('Please enter your age: '))
return age

except ValueError:
print('That was not a valid number. Please try again.')

def checkAge(age,min=18,max=31):
if age in list(range(min, max)):
print('Come on in!')
elif age < min:
print('Sorry, too young.')
elif age > max:
print('Sorry, too old.')

getName()
a=getAge()
checkAge(a)

For my part, i wouldn't loop getAge(à this way : i dislike infinite
loop.
I prefer to return None when ther is an error and check for None in the
main program

def getAge():
try:
age = int(input('Please enter your age: '))
return age

except ValueError:
print('That was not a valid number. Please try again.')
return None

getName()
a=getAge()
if a!=None:
checkAge(a)

of i you want to loop in getAge() :

def getAge():
age=-1
while age<0:
try:
age = int(input('Please enter your age: '))

except ValueError:
print('That was not a valid number. Please try again.')

return age

I'm a beginner with python, perhaps it was not "pythonic", but i'm sure
someone will tell is it's not.
 
P

Peter Otten

simonh said:
In my attempt to learn Python I'm writing a small (useless) program to
help me understand the various concepts. I'm going to add to this as I
learn to serve as a single place to see how something works,
hopefully. Here is the first approach:
That works fine. Then I've tried to use functions instead. The first
two work fine, the third fails:
def getName():
name = input('Please enter your name: ')
print('Hello', name)

def getAge():
while True:
try:
age = int(input('Please enter your age: '))
break
except ValueError:
print('That was not a valid number. Please try again.')

def checkAge():
permitted = list(range(18, 31))
if age in permitted:
print('Come on in!')
elif age < min(permitted):
print('Sorry, too young.')
elif age > max(permitted):
print('Sorry, too old.')

getName()
getAge()
checkAge()

I get this error message: NameError: global name 'age' is not
defined.

I'm stuck, can someone help? Thanks.


Generally, when you calculate something within a function you tell it the
caller by returning it:
.... return 74
....74

And if you want a function to act upon a value you pass it explicitly:
.... if 18 <= age <= 30:
.... print("Come in")
.... else:
.... print("Sorry, you can't come in")
....Come in

To check the age determined by the get_age() function you do:
Sorry, you can't come in

Peter
 
J

James Mills

i think we should use raw_input('Please enter your name: ') instead of
input('Please enter your name: ')

Good point :) OP: Please take notes :)

cheers
James
 
P

Peter Otten

James said:
Good point :) OP: Please take notes :)

I think the OP is using Python 3.0. What used to cause trouble

Python 2.5.1 (r251:54863, Jul 31 2008, 23:17:43)
[GCC 4.1.3 20070929 (prerelease) (Ubuntu 4.1.2-16ubuntu2)] on linux2
Type "help", "copyright", "credits" or "license" for more information.1/0
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1, in <module>
ZeroDivisionError: integer division or modulo by zero

is now the way it should be:

Python 3.0 (r30:67503, Dec 4 2008, 11:26:28)
[GCC 4.1.3 20070929 (prerelease) (Ubuntu 4.1.2-16ubuntu2)] on linux2
Type "help", "copyright", "credits" or "license" for more information.Traceback (most recent call last):
1/0
'1/0'

Peter
 
S

simonh

Thanks for the many replies. Thanks especially to Pierre. This works
perfectly:

def getName():
name = input('Please enter your name: ')
print('Hello', name)

def getAge():
while True:
try:
age = int(input('Please enter your age: '))
return age

except ValueError:
print('That was not a valid number. Please try again.')

def checkAge(age,min=18,max=31):
if age in list(range(min, max)):
print('Come on in!')
elif age < min:
print('Sorry, too young.')
elif age >= max:
print('Sorry, too old.')

getName()
a = getAge()
checkAge(a)


I am running Python 3, sorry for not stating that originally.
 
T

Terry Reedy

cadmuxe said:
i think we should use raw_input('Please enter your name: ') instead of
input('Please enter your name: ')

3.0 input == 2.x raw_input
2.5 input == <kaput>

Posters: please include Python version used, as correct answers may
depend on that.
 
B

Bruno Desthuilliers

simonh a écrit :
Thanks for the many replies. Thanks especially to Pierre. This works
perfectly:
(snip)

Ok, now for some algorithmic stuff:
def checkAge(age,min=18,max=31):
if age in list(range(min, max)):
print('Come on in!')
elif age < min:
print('Sorry, too young.')
elif age >= max:
print('Sorry, too old.')


if age is neither greater than max nor lesser than min, then it's it in
range(min, max). IOW, you could just skip the first test:


def checkAge(age,min=18,max=31):
if age < min:
print('Sorry, too young.')
elif age >= max:
print('Sorry, too old.')
else:
print('Come on in!')

!-)
 
I

Ivan Illarionov

Thanks for the many replies. Thanks especially to Pierre. This works
perfectly:

def getAge():
    while True:
        try:
            age = int(input('Please enter your age: '))
            return age

        except ValueError:
            print('That was not a valid number. Please try again.')

You could also drop the while loop and the 'age' variable:

def getAge():
try:
return int(input('Please enter your age: '))
except ValueError:
print('That was not a valid number. Please try again.')
return getAge()
 
S

simonh

Thanks for the extra tips Ivan and Bruno. Here is how the program
looks now. Any problems?



import sys

def get_name():
name = input('Please enter your name: ')
print('Hello', name)

def get_age():
try:
return int(input('Please enter your age: '))
except ValueError:
print('That was not a valid number. Please try again.')
return get_age()

def check_age(age,min=18,max=31):
if age < min:
print('Sorry, too young.')
elif age >= max:
print('Sorry, too old.')
else:
print('Come on in!')

def again():
response = input('Try again? Y or N: ')
while response != "Y":
if response == 'N':
print('Program finished.')
input('Press any key to exit.')
sys.exit()
else:
return response
run()

def run():
get_name()
a = get_age()
check_age(a)
again()

run()
 
B

Bruno Desthuilliers

simonh a écrit :
Thanks for the extra tips Ivan and Bruno. Here is how the program
looks now. Any problems?



import sys

def get_name():
name = input('Please enter your name: ')
print('Hello', name)

This one would be better spelled "get_and_display_name" !-)
def get_age():
try:
return int(input('Please enter your age: '))
except ValueError:
print('That was not a valid number. Please try again.')
return get_age()

Warning : there's a recursion limit in Python. While there are very few
chances you hit it in this case, it may bite you one day if you start
using recursion instead of iteration.

def check_age(age,min=18,max=31):
if age < min:
print('Sorry, too young.')
elif age >= max:
print('Sorry, too old.')
else:
print('Come on in!')

def again():
response = input('Try again? Y or N: ')
while response != "Y":

You probably mean 'if response != "Y"' ?
if response == 'N':
print('Program finished.')
input('Press any key to exit.')
sys.exit()
else:
return response

This return value is never used in the calling code. And if the user
types anything else than "Y" or "N", the program will exit without even
a goodbye message.
run()

def run():
get_name()
a = get_age()
check_age(a)
again()


As far as I'm concerned, I'd write it that way:

def read_string(question, error=''):
if not error:
error = "That was not a valid string. Please try again."
while True:
result = input(question).strip()
if result:
return result
else:
print error

def read_int(question, error=''):
if not error:
error = "That was not a valid number. Please try again."
while True:
try:
return int(input(question).strip())
except ValueError:
print(error)


def check_in_range(obj, mini, maxi, if_ok=0, if_lesser=-1, if_greater=1)
if obj < mini:
return if_lesser
elif age >= max:
return if_greater
else:
return if_ok


def again(question="Try again ?", yes="Y", no="N"):
# XXX : see appropriate string formatting for Python 3
# in 2.x, I'd write it as:
# prompt = "%s (%s or %s): " % (question, yes, no)
prompt = question + " " + yes" + " or " + no + ": "
while True:
response = input(prompt)
if response in (yes, no):
return response == yes

def run():
name = read_string("Please enter your name: ")
print("Hello, ", name)
age = read_int("Please enter your age: ")
messages = {
0: "Come on in!",
-1: "Sorry, too young",
1: "Sorry, too old",
}
message_key = check_in_range(age, 18, 31)
print(messages[message_key])

def main():
while True:
run()
if not again():
print('Program finished.')
input('Press any key to exit.')
return


if __name__ == "__main__":
main()


NB : the 'if __name__ == "__main__"' will allow you to use your code as
both a script (ie : calling it as 'main' program) or as a module
(importing it from within another script or module so you can reuse the
functions), by only calling 'main()' if the file is used as a script.

HTH
 
C

Cedric Schmeits

the following would be nicer:

def run():
get_name()
a = get_age()
check_age(a)
again()

if __name__ == "__main__":
run()


In this setup your script will only be run if it's started by itself,
but when using a import, the functions from the script can be executed
separately.
 
A

Arnaud Delobelle

Ivan Illarionov said:
You could also drop the while loop and the 'age' variable:

def getAge():
try:
return int(input('Please enter your age: '))
except ValueError:
print('That was not a valid number. Please try again.')
return getAge()

That's not necessarily good advice as Python does not optimize
tail-calls.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Staff online

Members online

Forum statistics

Threads
473,755
Messages
2,569,534
Members
45,007
Latest member
obedient dusk

Latest Threads

Top