[Tutor] A slight bug in IDLE

Dave Angel davea at davea.name
Sun Jul 14 07:16:54 CEST 2013


On 07/14/2013 12:37 AM, Jim Mooney wrote:
> On 13 July 2013 20:03, Steven D'Aprano <steve at pearwood.info> wrote:
>
>>
>> I don't understand that last sentence.
>
>
> Ah, I can be marvelously unclear.  I keep forgetting telepathy only works
> on my home planet ;')

You still have done nothing to explain the "last sentence."  You obscure 
that fact by not even keeping the context as to what the sentence was. 
Repeating it for your edification, and our mystification:

"""Generators are one-off and input
is one-off, so they match well for testing, for instance.
"""

> I wiped everything out to start fresh with Py27, so this is just a very
> simple example of what worked in sending a few million test integers to my
> numbers-to-name program, which normally took typed input. The real test
> program used randoms to go up to the decillions and a straight count to go
> into the quadrillions, for about 40 tests (before my CPU overheated, this
> being Arizona ;')
>
> No doubt there is a standard way to do this, but I wanted to test the
> numbers program quickly, without mooching all over the net, so I threw
> something like this together:
>
> # The  module I import, inputter.py:
> #Using Python 2.7 on Win 7
>
> def inp():
>      x = raw_input('type a number: ')
>      return x
>
> def intest():
>      if int(inp()) < 10:
>          print('smallnum')
>      else:
>          print('bignum')
>
> def main():
>      intest()
>
> if __name__ == '__main__':
>      main()
>
>
> # The Test Program, test.py that imports the module above:
> # Using Python 2.7 on Win 7
>
> import inputter
>
> x = (x for x in xrange(8,13)) # much bigger, and sometimes random, in the
> real test program
>
> def testfunc():  # This is where my typed input is replaced
>      return next(x)
>
> inputter.inp = testfunc

That's monkey-patching.  You're reaching inside the module and modifying 
it.  That's fine since you wrote both of them, but it makes things quite 
hard to debug in more complex cases, and especially if you didn't write 
the target module.

>
> for cnt in range(0,5):
>      inputter.intest()
>
> '''result:
> smallnum
> smallnum
> bignum
> bignum
> bignum
> '''

One of the techniques the inputter module should have used is a 
callback.  You pass a function as a parameter, and it calls that 
function.  You can make a default value, of course, to make it easy to test.

Anyway, in inputter.py, you'd have

def intest(func=inp):
      if int(func()) < 10:
          print('smallnum')
      else:
          print('bignum')


and in your calling module, you would remove the monkeypatch, and just call

for cnt in range(0,5):
     inputter.intest(testfunc)


The real problem I have is with your original code.  It mixed input, and 
calculations inside the same function, so you had to patch things up to 
test it from outside.  If you had refactored it as I suggested way back 
then, and Steven suggested even better, this all would have been a 
non-problem.


-- 
DaveA



More information about the Tutor mailing list