2011年12月10日土曜日

Python 3 チュートリアルを Python 2 で試しながら読んでみた #1

Django が、Python 3 に対応していないので、Python の勉強をするなら Python 2 環境に慣れておかないとダメ。ということで、手元にある「Python チュートリアル 第2版」のコードを Python 2.7.2 (Windows XP) 上で試してみたよ。

とりあえず、Python 2 インタプリタをめいっぱい Python 3 互換で動くようにするために、次のようなスタートアップファイルを作成した。あくまで、対話環境の初期化ファイルなので、ファイルを指定して実行するときは、同じようなインポートをファイルごとに記述する必要がある。

# -*- coding: utf-8 -*-
from __future__ import division, print_function, unicode_literals
from future_builtins import ascii, filter, map, hex, oct, zip

それで、環境変数 PYTHONSTARTUP にそのファイルのパスを登録した。ちなみにエディタは、IDLE を使用している。設定は、フォントを FixedSys の10ptに変更し、Default Source Encoding を UTF-8 に変更した。ただし、IDLE 上のインタプリタでは、スタートアップファイルが反映されなかったので、Python (command line) で起動したインタプリタ上で実行している。

さて、チュートリアルを読み進めていこう。

最初の関門かなと思ったのは、「3.1.1 数値」の割り算の部分。Python 2 と Python 3 で動作が異なる部分だけど、スタートアップファイルの設定で、同じ動作をしてくれた。素晴らしい。

次の問題は、文字コード。日本人プログラマーなら1度は頭を悩ませたことがある問題。「3.1.3 Unicode について」のところも、スタートアップファイルの設定で、ほぼ同じ動作をしてくれた。

ここから先は、当分トラブルはなさそうだなと思っていたら、「4.1 if 文」に伏兵が潜んでいたよ。input 関数の引数にスタートアップファイルで設定したまま非 Ascii 文字を含む文字列を入れるとダメっぽい。input 関数は、テストコードくらいでしか使わないだろうけど、こういうエラーが生じることは覚えとかないとかな。

「4.2 for 文」で、print 文と print 関数の違いを見た。出力が、タプルとして評価された結果になってしまっている。スタートアップファイルの設定があれば問題はない。

「4.3 range() 関数」では、range 関数の戻り値を print 関数の引数としたとき、動作が異なるところが見られる。Python 3 の range 関数は、Python 2 の xrange 関数と同様に反復可能体 (iterable object) を返すが、Python 2 の range 関数はそうではないためだ。とりあえず、range 関数を使ったままのコードで for 文の動作は問題ない。

「4.7.1 引数のデフォルト値」で、Python 2 と Python 3 での input 関数の違いに遭遇。Python 2 の raw_input 関数が Python 3 での input 関数になったそうだ。Python 2 の input 関数は、Python 3 での eval(input()) になるらしい。

4章まで読了。次回は5章から。Pythonista 目指して頑張ろう。

  • Python 2.7.2

    >>> (50-5*6)/4
    5
    >>> 8/5
    1
    >>> 'Hello\u0020World !'
    'Hello\\u0020World !'
    >>> 'あいう'.encode('utf-8')
    
    Traceback (most recent call last):
      File "", line 1, in 
        'あいう'.encode('utf-8')
    UnicodeDecodeError: 'ascii' codec can't decode byte 0x82 in position 0: ordinal not in range(128)
    >>> x = int(input("整数を入れてください: "))
    整数を入れてください: 42
    >>> a = ['cat', 'window', 'defenestrate']
    >>> for x in a:
    ...     print(x, len(x))
    ...
    ('cat', 3)
    ('window', 6)
    ('defenestrate', 12)
    >>> print(range(10))
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    >>> list(range(5))
    [0, 1, 2, 3, 4]
    >>>
  • Python 2.7.2 (Python 3 互換設定済)

    >>> (50-5*6)/4
    5.0
    >>> 8/5
    1.6
    >>> 'Hello\u0020World !'
    u'Hello World !'
    >>> 'あいう'.encode('utf-8')
    b'\xe3\x81\x82\xe3\x81\x84\xe3\x81\x86'
    >>> x = int(input("整数を入れてください: "))
    Traceback (most recent call last):
      File "", line 1, in 
    UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-9: ordinal not in range(128)
    >>> a = ['cat', 'window', 'defenestrate']
    >>> for x in a:
    ...     print(x, len(x))
    ...
    cat 3
    window 6
    defenestrate 12
    >>> print(range(10))
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    >>> list(range(5))
    [0, 1, 2, 3, 4]
    >>>
  • Python 3.2.1

    >>> (50-5*6)/4
    5.0
    >>> 8/5
    1.6
    >>> 'Hello\u0020World !'
    'Hello World !'
    >>> 'あいう'.encode('utf-8')
    b'\xe3\x81\x82\xe3\x81\x84\xe3\x81\x86'
    >>> x = int(input("整数を入れてください: "))
    整数を入れてください: 42
    >>> a = ['cat', 'window', 'defenestrate']
    >>> for x in a:
    ...     print(x, len(x))
    ...
    cat 3
    window 6
    defenestrate 12
    >>> print(range(10))
    range(0, 10)
    >>> list(range(5))
    [0, 1, 2, 3, 4]
    >>>

参考文献