パスワードを忘れた? アカウント作成
42084 journal

hylomの日記: Python 3.0リリース、仕様変更多数 39

日記 by hylom

12月3日、Python 3.0がリリースされました。Python 3.0はPython 3000とも呼ばれており、Python 2.x系から大幅な仕様変更が加えられています。

主な(そして注意すべき)変更点は「What's New In Python 3.0」にまとめられていますが、「Python 2.xとは互換性が無い」と言われるように、かなりの仕様変更が行われています。主立ったものをまとめると、

  • print文が関数となり、色々と仕様も変更された。もう「print "ほげほげ",」という記法は使えない
  • 「dict.keys()」や「dict.items()」、「dict.values()」といったDictionaryを扱ういくつかの関数の動作が変更され、リストの代わりにViewやIteratorを返すようになった
  • 比較演算子(<、>、<=、>=)の仕様変更。明らかに不自然な比較(たとえば「1 < ''」「len <= len」など)はエラーになるようになった。また、cmp()(と__cmp__())関数は廃止になった
  • long型がint型にリネームされた。そして従来のint型は廃止になった
  • int同士の割り算がfloatを返すようになった(たとえば1/2の結果は0.5)。整数を返したい場合、「//」演算子を使う
  • 文字列とバイナリ列が区別されるようになり、文字列はstr型を、バイナリ列はbytes型を使うようになった。str型はUnicodeで文字列が格納される。それにともない、従来「u"ほげほげ"」などと表現していたUnicode文字列は「"ほげほげ"」と表記できるようになった。さらに、「\u」「\U」は通常の文字列(そのまま\u、\Uという文字列)として扱われるようになった。
  • nonlocalステートメント、「(a, b, *rest) = <シーケンス>」、「0o720」、「0b1010」など、新しい文法が導入された
  • gopherlibやmd5など、いくつかの標準モジュールが廃止された(md5はhashlibにリプレスされた)
  • いくつかの標準モジュールがリネームされた。たとえば「SocketServer」は「socketserver」に、「repr」は「reprlib」に、など
  • 標準モジュールで関連のあるパッケージがまとめられた。たとえばhttplibやBaseHTTPServer、CGIHTTPServer、SimpleHTTPServer、Cookie、cookielibはhttpというパッケージにまとめられている

などとなりますが、そのほか文字列周りや文法には多数の仕様変更が加えられています。詳細は自身でご確認ください。

今回のアップデートでは前バージョンとの互換性を切り捨てているため、不安に思われる方も多いとは思いますが、この仕様変更により、言語仕様やライブラリの一貫性や分かりやすさが向上していると感じます。これから新規にPython開発をされるかたは、是非Python 3.0を使ってください。

(といってもレンタルサーバなどではなかなか入れ替えられないんだけどね……)。

この議論は賞味期限が切れたので、アーカイブ化されています。 新たにコメントを付けることはできません。
  • by yasiyasi (5450) on 2008年12月05日 15時37分 (#1468125)
    atsさんのブログ記事「みんなが言及しないPython 3.0のステキ機能」 [coreblog.org]のコメントにある,新機能のサンプルを見て,笑ってしまった。

    Re:みんなが言及しないPython 3.0のステキ機能
    投稿者 NoboNobo 投稿日時: 2008年12月05日 12時03分
    なんと、変数名に漢字が使えますよ!

    >>> 漢字=123
    >>> print(漢字)
    123
    これに対するatsさんの返事も,秀逸なんだけど,まあリンク先まで読みに行ってみてくださいな。

    Python 2.5から10進演算も使えるし,「COBOLの移行先」を目指して開発されている・・・・わけではないな,うん。
    • >> なんと、変数名に漢字が使えますよ!
      これで自作スクリプトがぐっと作りやすくなりました。

      英語でソレっぽい識別子名を考えなくては!という悩みが軽減されます。善哉。
      親コメント
    • by Anonymous Coward
      > なんと、変数名に漢字が使えますよ!
      Javaは大昔から、JavaScriptもいつからか知りませんが普通に日本語識別子が使えますし、Perl 5.8以降はuse encoding Filter=>1で、Rubyは-Kオプションで日本語の識別子が使えます。むしろ「やっと?」という感じです。今さらすぎるから誰も言及しないのではないでしょうか。
      • by Anonymous Coward
        ですよねぇ。
        ぴゅう太なんてもうずっと前から日本g(ry
  • by T.Sawamoto (4142) on 2008年12月05日 14時37分 (#1468089)
    2to3.py(非互換チェックツール)を使って少しずつスクリプトを修正しているのですが、少々トラブルに出くわしました。
    zipファイル形式の圧縮/伸張ライブラリzipfile.ZipFileで、ファイル名エンコーディングがUTF-8決めうちになってしまったようです。

    従来のzipfile.ZipFile.writeは、zipに格納されるファイル名に8ビット文字列をそのまま使っていたため、エンコーディングを自分で選ぶことができました。
    (とゆーか、ライブラリ側が関知するところではなかった(^^;))
    しかし、Python3.0からはUNICODE文字列で与える形式となり、かつ今のところエンコーディングを変更することはできないみたい。

    import zipfile
    z = zipfile.ZipFile('hoge.zip', 'w', zipfile.ZIP_DEFLATED)
    z.write('はろー.txt')
    z.close()
    # ↑こうすると、Windowsでは解凍時にファイル名が文字化け。
    # WindowsではShift_JIS(CP932)が一般的なので。

    元々zipファイルはファイル名エンコーディングに問題を含んでいて、MacOSXで圧縮したzipをWindows側で解凍するとファイル名が文字化けするといったことが起きていたわけですけど、これがPython3.0で表面化してしまった感じですねー。

    仕方ないので、zipfileを使っていたところをtarfileに置き換えて修正を進めてます。
    標準がUNICODE文字列であることは実際便利で、今までエンコーディング変換で手間をかけていたところがすっきり書けるのは良いんですけど、しばらくは様々な問題が頻出しそうな予感がします。
    • zipfileはマルチバイト圏だけでなく、Latin-1圏でも問題になりそうな仕様変更ですね。
      親コメント
    • by Anonymous Coward
      リファレンス [python.org]には

      Note
      There is no official file name encoding for ZIP files. If you have unicode file names, you must convert them to byte strings in your desired encoding before passing them to write(). WinZip interprets all file names as encoded in CP437, also known as DOS Latin.

      って書いてあるけど、これってファイルネームを自分でエンコードしたbytesで渡せってことだよね。
      未確認だけどこれでできないの?
      • by T.Sawamoto (4142) on 2008年12月05日 17時45分 (#1468247)
        #1468217さんがおっしゃるとおり、2.6以前のときの使い方ですね。

        3.0の zipfile.py を参照すると、圧縮時はまず 'ascii' でエンコードしてみて、例外が出るようなら 'utf-8' で再度エンコードします。(zipfile.py:335)

        # このときフラグ(0x800)を立てているようですが、Vistaエクスプローラ/Lhplus/+Lhaca等の解凍ツールはチェックしてないみたいで、いずれもUTF-8は文字化けしちゃいます。

        解凍時はフラグを見て、0x800が立っていたら 'utf-8'、そうでなければ 'cp437' でファイル名をデコードします。(zipfile.py:759)
        つまり、cp437(DOS-US)だけは正常に解凍できるという極悪仕様(^^;)
        親コメント
        • by Anonymous Coward
          おっとこっち [python.org]が3.0ですね。
          いや、3.0でも同じですね。
          ということは、仕様というよりは実装の問題ですから、言えばすぐに直されるんじゃないでしょうか。
          • by T.Sawamoto (4142) on 2008年12月05日 20時59分 (#1468360)
            3.0の方もそう記述されてましたか。
            ただ、現実問題として「すぐに直せる」レベルかどうかは少し微妙かもです。

            ちょっと今は試せないんですが(作業が残っているため、まだ自宅マシンには導入できない(^^;))、3.0からは文字列がUNICODEになってしまった(8ビットの方はバイト列扱いのbytes型になった)ので、多分ですが中でエンコード/デコードが必要になってくると思われます。
            現状だとファイル名エンコーディングを明示するインターフェースがZipFileに存在しないため、仕様を追加しないと対応は難しいんじゃないかと。

            そもそもは現状の、「zip内ファイル名エンコーディングが環境依存」という状況が良くないんですよね……。
            どのみちOSX等とのやり取りで支障を来しているので、私はこの際zipを捨ててtar.gzに移行する予定です(^^;)
            親コメント
            • by Anonymous Coward
              zipfile.pyで勝手にencode、decodeされているのは6ヶ所くらいなので、さほどの手間では
              ないでしょうが、この手の問題は他にもいろいろな場面ででてきそうですね。

              一つの対処法としてstrやbytesのメンバーとしてencodingを設定できるようにするのは
              どうだろう。これなら意図したとおりに変換できるし、自動変換させればstrとbytesを
              演算可能にもできる。
              • by Anonymous Coward on 2008年12月06日 14時51分 (#1468698)
                とりあえず次のパッチは多分必須

                --- zipfile2.py 2008-12-06 12:35:52.000000000 +0900
                +++ Python-3.0/root/usr/local/lib/python3.0/zipfile.py 2008-12-06 10:50:20.000000000 +0900
                @@ -877,8 +877,7 @@
                                  if fheader[_FH_EXTRA_FIELD_LENGTH]:
                                          zef_file.read(fheader[_FH_EXTRA_FIELD_LENGTH])

                -# if fname != zinfo.orig_filename.encode("utf-8"):
                - if fname != zinfo.orig_filename.encode("utf-8" if zinfo.flag_bits & 0x800 else "cp437"):
                + if fname != zinfo.orig_filename.encode("utf-8"):
                                          raise BadZipfile(
                                                      'File name in directory %r and header %r differ.'
                                                      % (zinfo.orig_filename, fname))
                別の場所で'utf-8'と'cp437'を分けてエンコードしてるのに、ここでは'utf-8'決め打ちという
                のは完全なミスでしょう。

                あとはファイル名に関しては

                if info.flag_bits & 0x800:
                    filename = info.filename
                else:
                    filename = info.filename.encode('cp437').decode('cp932')
                という感じでやれば、cp437とcp932の文字コードの共通の範囲内ならば、変換可能。

                今回3.0を使ってみて、bytesとstrの互換性の無さが気になった。
                'abc'+b'123'やb'asd'.index('s')がエラーになるのは使いにくい。
                親コメント
        • by Anonymous Coward

          解凍時はフラグを見て、0x800が立っていたら 'utf-8'、そうでなければ 'cp437' でファイル名をデコードします。(zipfile.py:759)
          つまり、cp437(DOS-US)だけは正常に解凍できるという極悪仕様(^^;)

          appnote [pkware.com]のAPPENDIX D - Language Encoding (EFS)に従っただけですね。確かに cp437 だけってのは互換性に対する配慮が足りないという気はしますが、Java の java.util.zip みたいにフラグも立てずに utf-8 で出力するよりはマシだと思います。
      • by Anonymous Coward
        このドキュメントはPython2.6のものですね。
    • by Anonymous Coward
      >zipファイル形式の圧縮/伸張ライブラリzipfile.ZipFileで、
      >ファイル名エンコーディングがUTF-8決めうちになってしまったようです。

      それってjarファイルじゃないですか。

      しかし、思ったのはやっぱりリリースされてから
      試さない人がいるから、それなりの品質でもリリースしてしまった方がいいんだなぁ、ということ。

      # MSはよく分かってる
  • raw string (スコア:3, 参考になる)

    by T.Sawamoto (4142) on 2008年12月05日 15時57分 (#1468141)
    タレコミ文にある

    ……さらに、「\u」「\U」は通常の文字列(そのまま\u、\Uという文字列)として扱われるようになった。
    はちょっと違いますー。
    “「\」はraw文字列内において、常に字義通りに解釈されるようになった”
    ぐらいがより正確なのではないかと。
    rawでない普通の文字列リテラルでは当然「\u」が使えますので。
    (じゃないと文字コード指定できないことに……)

    Pythonでは文字列リテラルとしてraw文字列というものがあります。
    リテラル中で「\」をエスケープさせたくないばやいに使うもので、文字列の前に r を付け加えることでraw文字列になります。
    (正規表現の記述で重宝)
    但し、2.6以前ではUNICODE16進指定のみ、文字コード指定であると解釈されるという実装になっていました。

    >>> '\1'
    '\x01'
    >>> r'\1'
    '\\1'
    >>> ur'\u0021'
    u'!'
    これが、3.0以降からはUNICODE16進指定も無視され、raw文字列中の「\」は全てそのままの文字として出力されることになります。

    >>> '\1'
    '\x01'
    >>> r'\1'
    '\\1'
    >>> r'\u0021'
    '\\u0021'
  • by nekopon (1483) on 2008年12月05日 13時23分 (#1468038) 日記

    水準3000

    # 5文字までとかいやすぎ

  • 他の言語がどんどんと複雑になっていく中、Perlにシンプルさは最高に美しい。

    # で、Perl6ってどうなるんだっけ?
    • by shimotsuki (2505) on 2008年12月05日 13時50分 (#1468056) ホームページ
      シンプルか?というのは疑問な気が・・・。

      むしろPerlは後方互換性が今のところそれなりに確保されている点に賛辞を送りたい。
      それゆえに抱えている問題はあるかもしれませんが、どんどん変わっていく言語ではコードを書く気になりません。

      Perl6? 何それ? (笑
      まぁとりあえず期待はしています。
      親コメント
    • by Anonymous Coward on 2008年12月05日 13時51分 (#1468057)
      perlがシンプルとかいう奴初めて見た。

      ## がらくた折衷言語だろ?

      python3.0は言語仕様の変更もさることながら、標準ライブラリの変更も大きい。
      まぁ公式でもすぐに切り替えようという話ではないので、暫くは2.xでも問題ないな。

      言語ではないところでは、Ubuntu HardyだとLANG=Cじゃないとコンパイルでこけるのはプチはまったけどね。
      親コメント
      • Re:Perl教徒としては (スコア:2, すばらしい洞察)

        by nekopon (1483) on 2008年12月05日 14時23分 (#1468082) 日記

        他の言語がどんどんと複雑になっていく中、Perl シンプルさは最高に美しい。

        # 強調は引用者

        シンプルに書かれた Perl は美しいと思いませんか。

        親コメント
        • Re:Perl教徒としては (スコア:5, おもしろおかしい)

          by Anonymous Cowboy (6205) on 2008年12月05日 17時01分 (#1468207)
          >シンプルに書かれた Perl

          同じ処理をするとして
          ・単純な処理を明快に積み重ねて20行で書かれた処理(理解するのに2分)

          ・変態じみた正規表現を駆使して2行で書かれた処理(理解するのに20分)
          だと
          後者を「シンプル」だと思ってしまうのがPerl教徒の恐ろしいところ
          親コメント
      • by Anonymous Coward
        同意。かっこ悪いオブジェクト指向入れたとこで見切りをつけた。シンプルならawk/sedでいいや
    • by kabuchan (37144) on 2008年12月05日 20時02分 (#1468338)
      perlのよさは今まで学習してきた言語知識を
      使いまわせるとこだと思います

      pythonはただでさえ独自仕様が多くてとっつきにくいのに
      前バージョンを踏襲さえしないのはどうかな
      親コメント
      • by knishida (27993) on 2008年12月05日 21時09分 (#1468369)
        > perlのよさは今まで学習してきた言語知識を
        > 使いまわせるとこだと思います

        「今まで学習してきた言語知識」とはどの言語?

        オブジェクト指向をJava辺りで学んだ身としては、Perlのオブジェクト指向には
        どうにも馴染めなくて覚えるのをやめました。

        Perlのよさは、手軽なテキスト処理と、豊富なライブラリ資産かなと思います。
        今でもちょっとした(数十行程度の)スクリプトを書くならPerlが一番ですね。

        一方で数万行を超えるような、きちんと設計して書くアプリケーションになると、
        PythonやRubyのような言語のほうが自分にはなじみやすいです。
        (最終的には慣れの問題だとは思いますけれども)
        親コメント
        • Perlのへなちょこオブジェクト指向実装は、
          冗談とPerlなりの真面目さの折衷なのです。たぶん。
          オブジェクト指向なんつって、こんなもんでもできるだろっていう。

          # ハッカー流ジョークとしては最高に面白い部類に入ると思ってます。実用的だし。
          親コメント
        • by Anonymous Coward
          元ACではありませんがマジレスすると、sed/awk/C あたりではないでしょうか。
          最近ならPHPを足してもいいかな。
    • by Anonymous Coward
      シンプルと言えばC言語だろJK。
      #言語としてはシンプルだが、ポインタバグは悪夢。

      C++?なにそれ?美味しいの?
      • by Anonymous Coward
        >言語としてはシンプルだが、ポインタバグは悪夢。

        Java好きのWebプログラマはよくそんなことをいうけれど、
        それぞれの言語なりの解決策はノウハウとしてあるとしても、マシン語での実装がイメージできるのに言語の制約でできなくて感じる理不尽な気分はポインタが生みだす災害を予防する努力よりもぐっと憂鬱です。

        書くプログラムが低レベルか高レベルかによって、憂鬱に思う機会の多少が異なるのでアレですが。

        • by Anonymous Coward
          > マシン語での実装がイメージできるのに言語の制約でできなくて感じる理不尽な気分

          なるほどねえ
          Cでの整数オーバーフローのハンドリングはイライラしますもんね
  • by Anonymous Coward on 2008年12月05日 14時46分 (#1468094)
    その為に用意されてるのだし、今後も2.X系のサポートは当分続きます。
  • これから新規にPython開発をされるかたは、是非Python 3.0を使ってください。

    ライブラリやフレームワークは現時点でどのくらい対応しているんでしょうか?

    # Djangoで遊び始めたのでそのへんも気になる
  • by Anonymous Coward on 2008年12月05日 14時51分 (#1468097)
    >gopherlibやmd5など、いくつかの標準モジュールが廃止された(md5はhashlibにリプレスされた)

    リプレス(repress)は(欲求を)「抑止する」「抑圧する」

    意図していたのはreplaceですね? [Y/y]

    # いけないマコちゃんなのでAC

  • by Anonymous Coward on 2008年12月05日 16時14分 (#1468162)
    てっきり「変なモノ」セクションで代用するのかと
    命名元的に
    • by Anonymous Coward
      変なものなんて・・・
      いや、ほめ言葉なのか?
    • by Anonymous Coward
      何言ってるんですか。命名元のトピックですよ?
typodupeerror

Stableって古いって意味だっけ? -- Debian初級

読み込み中...