Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Beginner trying to understand functions.

0 views
Skip to first unread message

simonh

unread,
Dec 8, 2008, 8:32:06 AM12/8/08
to
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.

James Mills

unread,
Dec 8, 2008, 8:56:10 AM12/8/08
to simonh, pytho...@python.org
On Mon, Dec 8, 2008 at 11:32 PM, simonh <simonhar...@googlemail.com> wrote:
> 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 :)

--
--
-- "Problems are solved by method"

Pierre-Alain Dorange

unread,
Dec 8, 2008, 8:57:02 AM12/8/08
to
simonh <simonhar...@googlemail.com> wrote:

> 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.

--
Pierre-Alain Dorange <http://microwar.sourceforge.net/>

Ce message est sous licence Creative Commons "by-nc-sa-2.0"
<http://creativecommons.org/licenses/by-nc-sa/2.0/fr/>

Peter Otten

unread,
Dec 8, 2008, 9:00:54 AM12/8/08
to
simonh wrote:

> 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


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

>>> def get_age():
... return 74
...
>>> get_age()
74
>>> age = get_age()
>>> age
74

And if you want a function to act upon a value you pass it explicitly:

>>> def check_age(age):
... if 18 <= age <= 30:
... print("Come in")
... else:
... print("Sorry, you can't come in")
...
>>> check_age(10)
Sorry, you can't come in
>>> check_age(20)
Come in

To check the age determined by the get_age() function you do:

>>> age = get_age()
>>> check_age(age)
Sorry, you can't come in

Peter

acerimusdux

unread,
Dec 8, 2008, 9:04:44 AM12/8/08
to pytho...@python.org
simonh write:
> 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.')
>
>
>

You are running into Python's scoping rules. Variables in Python are not
global by default, they are local to their scope. Each function has it's
own scope (but blocks like if: and while: don't.) So your variable "age"
only exists in
getage(). It doesn't exist in checkage(). You could simply add a
"global age" statement to getAge() before you first use the age
variable, and that will likely work.

Or, rather than declare it global, you might want to have getage()
return a value, and then pass it to checkage () as a function parameter.
Add a "return age" statement to getage() before "break". Then, for your def:

def checkage(age):

And then when calling:

A=getAge()
checkAge(A)



James Mills

unread,
Dec 8, 2008, 9:38:06 AM12/8/08
to cadmuxe, pytho...@python.org
On Tue, Dec 9, 2008 at 12:24 AM, cadmuxe <cad...@gmail.com> wrote:
> 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

Peter Otten

unread,
Dec 8, 2008, 9:46:07 AM12/8/08
to
James Mills wrote:

> On Tue, Dec 9, 2008 at 12:24 AM, cadmuxe <cad...@gmail.com> wrote:
>> i think we should use raw_input('Please enter your name: ') instead of
>> input('Please enter your name: ')
>
> 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.
>>> input()
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.
>>> raw_input()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'raw_input' is not defined
>>> input()
1/0
'1/0'

Peter

James Mills

unread,
Dec 8, 2008, 9:53:32 AM12/8/08
to Peter Otten, pytho...@python.org
On Tue, Dec 9, 2008 at 12:46 AM, Peter Otten <__pet...@web.de> wrote:
> I think the OP is using Python 3.0. What used to cause trouble

Well of course he/she/it is!
I'm too blind to have noticed that! :)

--JamesMills

cadmuxe

unread,
Dec 8, 2008, 9:59:53 AM12/8/08
to
On 12月8日, 下午10时53分, "James Mills" <prolo...@shortcircuit.net.au>
wrote:

> On Tue, Dec 9, 2008 at 12:46 AM, Peter Otten <__pete...@web.de> wrote:
> > I think the OP is using Python 3.0. What used to cause trouble
>
> Well of course he/she/it is!
> I'm too blind to have noticed that! :)
>
> --JamesMills
>
> --
> --
> -- "Problems are solved by method"

oh,i think i should go to read the new document of py3k
thanks for all

simonh

unread,
Dec 8, 2008, 1:02:05 PM12/8/08
to
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.

Terry Reedy

unread,
Dec 8, 2008, 5:09:34 PM12/8/08
to pytho...@python.org
cadmuxe wrote:
> 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.

Bruno Desthuilliers

unread,
Dec 9, 2008, 4:17:02 AM12/9/08
to
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!')

!-)


Ivan Illarionov

unread,
Dec 9, 2008, 5:43:38 AM12/9/08
to
On Dec 8, 9:02 pm, simonh <simonharrison...@googlemail.com> wrote:
> Thanks for the many replies. Thanks especially to Pierre. This works
> perfectly:

<snip>

> 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()

simonh

unread,
Dec 9, 2008, 6:21:29 AM12/9/08
to
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()


Bruno Desthuilliers

unread,
Dec 9, 2008, 8:50:58 AM12/9/08
to
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

Cedric Schmeits

unread,
Dec 9, 2008, 8:53:06 AM12/9/08
to
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.

Arnaud Delobelle

unread,
Dec 9, 2008, 3:31:15 PM12/9/08
to
Ivan Illarionov <ivan.il...@gmail.com> writes:

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

--
Arnaud

0 new messages