Re: [Tutor] Function works one time then subsequently fails

2015-04-29 Thread Alan Gauld

On 29/04/15 04:58, Jim Mooney Py3winXP wrote:


numbers = []


Note that you chose to make this global.


def parse_string(math_string):
 """Input: A math string with a verbal or mathematical operation
 and two valid numbers to operate on. Extra numbers and operations
 are ignored. Output: A tuple containing a function corresponding
 to the operation and the two numbers. Returns None on failure.
 """


General comment. returning a mixture of None and valid data
is a recipe for confusion later. Its better to fail by
raising an exception, say a ValueError for example,
or even create a bespoke error.


 operation = None
 tokens = math_string.split()
 for token in tokens:
 if token in operations:
 operation = operations[token]
 elif test_number(token) != None:
 numbers.append(test_number(token))
 if len(numbers) > 1:
 break
 if operation is None or len(numbers) < 2:
 return None
 else:
 return operation, numbers[0], numbers[1]

REPL

result = parse_string('1 minus 15')
func, number1, number2 = result
func(number1, number2)

-14

result = parse_string('1 minus 15')
print(result)

None


You never empty numbers so it already contains >1 numbers.
Your loop breaks. And operation is None.
So you return None.

That's why raising an error with suitable text would be clearer.

--
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.amazon.com/author/alan_gauld
Follow my photo-blog on Flickr at:
http://www.flickr.com/photos/alangauldphotos


___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Function works one time then subsequently fails

2015-04-28 Thread Cameron Simpson

On 28Apr2015 22:27, Jim Mooney Py3winXP  wrote:

On 28 April 2015 at 21:27, Cameron Simpson  wrote:

At a first glance numbers is a global. It is reset to [] at program start,
but never again. So you're appending to it forever. I have not investigated
further as to how that affects your program's flow.


Took you less time to find that than me. I, of course, realized I forgot to
empty the number list on each time through the parse loop, After I posted
;')  Seems to work okay otherwise, although criticism of Pythonicity is
welcome. I just wanted to practice tossing functions around. I'll put it
into a user input loop and work it. It won't catch everything. I have to
study regexes for that.


Basicly, you should almost never have a global variable. There is a host of 
special circumstances where globals solve some specific problems. But by and 
large, don't do it without a very concrete reason.


If numbers had been local to the parse function you would never have been 
bitten by this. There's no need for it to be global; you can return the 
operator and the operands (numbers) easily from the parse function.



At this point I'm starting to lose track and have to think of better ways
to organize so I recall and understand what I'm doing. I know there are
general tuts on that but that's just reading. Is there a python-specific
tut on it where I could follow actual code along with the interpreter to
reinforce things? Or, what is the official word for
organize-so-you-don't-forget-or-get-confused so I can search google with it?


"functional decomposition"?

One rule of thumb is that functions should be short. That way you can generally 
keep their purpose and internal oparations in your head in one go, and the 
whole thing also fits on your screen.


As with all things, sometimes that cannot be reasonably achieved, but it is 
usually so.


We can pick over your code as well if you like. Should we?

Cheers,
Cameron Simpson 

If this experiment we're doing works, then I will follow up and push it as
hard as possible. And if it doesn't work, I will write a science-fiction
novel where it does work. It's a win-win situation.
- John Cramer on his experiment for possible cuasality violation
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Function works one time then subsequently fails

2015-04-28 Thread Jim Mooney Py3winXP
On 28 April 2015 at 21:27, Cameron Simpson  wrote:

> At a first glance numbers is a global. It is reset to [] at program start,
> but never again. So you're appending to it forever. I have not investigated
> further as to how that affects your program's flow.
>
> Cheers,
> Cameron Simpson 
>

Took you less time to find that than me. I, of course, realized I forgot to
empty the number list on each time through the parse loop, After I posted
;')  Seems to work okay otherwise, although criticism of Pythonicity is
welcome. I just wanted to practice tossing functions around. I'll put it
into a user input loop and work it. It won't catch everything. I have to
study regexes for that.

At this point I'm starting to lose track and have to think of better ways
to organize so I recall and understand what I'm doing. I know there are
general tuts on that but that's just reading. Is there a python-specific
tut on it where I could follow actual code along with the interpreter to
reinforce things? Or, what is the official word for
organize-so-you-don't-forget-or-get-confused so I can search google with it?

-- 
Jim

If you only had one hour left to live, would you spend it on Facebook,
Twitter, or Google Plus?
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Function works one time then subsequently fails

2015-04-28 Thread Cameron Simpson

On 28Apr2015 20:58, Jim Mooney Py3winXP  wrote:

This is really puzzling me. I'm parsing a string to do some simple math
operations and practice tossing functions around. My parser works on the
first run, then it continually fails on the same input.


[...]

numbers = []

[...]

def parse_string(math_string):
   """Input: A math string with a verbal or mathematical operation
   and two valid numbers to operate on. Extra numbers and operations
   are ignored. Output: A tuple containing a function corresponding
   to the operation and the two numbers. Returns None on failure.
   """
   operation = None
   tokens = math_string.split()
   for token in tokens:
   if token in operations:
   operation = operations[token]
   elif test_number(token) != None:
   numbers.append(test_number(token))
   if len(numbers) > 1:
   break

[...]

At a first glance numbers is a global. It is reset to [] at program start, but 
never again. So you're appending to it forever. I have not investigated further 
as to how that affects your program's flow.


Cheers,
Cameron Simpson 

There are two ways of dealing with this problem: one is complicated and
messy, and the other is simple and very elegant. We don't have much time
left, so I'll just show you the complicated and messy way.
- Richard Feynman, 1981
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


[Tutor] Function works one time then subsequently fails

2015-04-28 Thread Jim Mooney Py3winXP
This is really puzzling me. I'm parsing a string to do some simple math
operations and practice tossing functions around. My parser works on the
first run, then it continually fails on the same input.

"""
Takes the name of a binary math operation and two numbers from input,
repeatedly, and displays the results until done
"""

def add(a, b):
return a + b

def subtract(a, b):
return b - a

def minus(a, b):
return a - b

def multiply(a, b):
return a * b

def divide(a, b):
return a / b

operations = {'add': add, '+': add, 'plus': add, 'subtract': subtract,
  '-': minus, 'minus': minus, 'multiply': multiply, '*':
multiply,
  'times': multiply, 'divide': divide, '/': divide,
  'divided': divide}

numbers = []

def test_number(astring):
"""
Input: A string that should represent a valid int or float. Output:
An int or float on success. None on failure.
"""
for make_type in (int, float):
try:
return make_type(astring)
except ValueError:
pass
return None

def parse_string(math_string):
"""Input: A math string with a verbal or mathematical operation
and two valid numbers to operate on. Extra numbers and operations
are ignored. Output: A tuple containing a function corresponding
to the operation and the two numbers. Returns None on failure.
"""
operation = None
tokens = math_string.split()
for token in tokens:
if token in operations:
operation = operations[token]
elif test_number(token) != None:
numbers.append(test_number(token))
if len(numbers) > 1:
break
if operation is None or len(numbers) < 2:
return None
else:
return operation, numbers[0], numbers[1]

REPL
>>> result = parse_string('1 minus 15')
>>> func, number1, number2 = result
>>> func(number1, number2)
-14
>>> result = parse_string('1 minus 15')
>>> print(result)
None
>>> result = parse_string('1 minus 15')
>>> print(result)
None
>>>


-- 
Jim

If you only had one hour left to live, would you spend it on Facebook,
Twitter, or Google Plus?
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor