views:

113

answers:

3

This script will run as expected and pass doctests without any errors in Python 2.6:

def num_even_digits(n):
    """
      >>> num_even_digits(123456)
      3
      >>> num_even_digits(2468)
      4
      >>> num_even_digits(1357)
      0
      >>> num_even_digits(2)
      1
      >>> num_even_digits(20)
      2
    """


    count = 0
    while n:
        digit=n%10
        if digit%2==0:
            count+=1
            n/=10
        else:
            n/=10

    return count



if __name__ == '__main__':
    import doctest
    doctest.testmod()

In Python3.0 this is the output:

**********************************************************************
File "/home/calder/My Documents/Programming/Python Scripts/ch06.py", line 3, in                            
 __main__.num_even_digits`
Failed example:
    num_even_digits(123456)
Expected:
    3
Got:
    1
**********************************************************************
File "/home/calder/My Documents/Programming/Python Scripts/ch06.py", line 5, in                   
__main__.num_even_digits
Failed example:
    num_even_digits(2468)
Expected:
    4
Got:
    1
**********************************************************************
1 items had failures:
   2 of   5 in __main__.num_even_digits
***Test Failed*** 2 failures.

I have tried running the Python script "2to3", but no changes are needed it says. Does anyone know why the script will not run in Python 3?

+11  A: 

I'm guessing you need n //= 10 instead of n /= 10. In other words, you want to explictly specify integer division. Otherwise 1 / 10 will return 0.1 instead of 0. Note that //= is valid python 2.x syntax, as well (well, starting with version ~2.3, I think...).

Joe Kington
In order to use the `//=` syntax (and to replace the `/=` default) in 2.x one must include `from __future__ import division`.
Andrew
@Andrew - `from __future__ import division` only changes what the default `/` operator does, the `//` operator has been around for quite awhile and doesn't require the `from __future__ import division` bit. `10 // 2` --> `5` even as far back as python 2.2 (which is the oldest interpreter I have access to, at the moment).
Joe Kington
@Andrew, half-right, half-wrong: without the import, the default stays the same (`/` between integers truncates, like `//`), but `//=` still works perfectly fine with _or_ without the import.
Alex Martelli
+2  A: 

I think this could be because operator "/=" in Python 2.x returned integer result while in Python 3.x it returns float. Try to change "/=" to "//=". "//=" return integer result in Python 3.x in the same way as "/=" in Python 2.x.

Zuljin
+5  A: 

And now for something completely different:

count = 0
while n:
   n, digit = divmod(n, 10)
   count += ~digit & 1
John Machin