「Python 3.0」リリース、仕様変更多数 39
ストーリー by GetSet
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を使ってください。
非ASCII文字への対応強化 (スコア:5, 参考になる)
Python 2.5から10進演算も使えるし,「COBOLの移行先」を目指して開発されている・・・・わけではないな,うん。
Re:非ASCII文字への対応強化 (スコア:1)
これで自作スクリプトがぐっと作りやすくなりました。
英語でソレっぽい識別子名を考えなくては!という悩みが軽減されます。善哉。
Re: (スコア:0)
Javaは大昔から、JavaScriptもいつからか知りませんが普通に日本語識別子が使えますし、Perl 5.8以降はuse encoding Filter=>1で、Rubyは-Kオプションで日本語の識別子が使えます。むしろ「やっと?」という感じです。今さらすぎるから誰も言及しないのではないでしょうか。
Re: (スコア:0)
ぴゅう太なんてもうずっと前から日本g(ry
UNICODE文字列に起因する問題 (スコア:3, 参考になる)
zipファイル形式の圧縮/伸張ライブラリzipfile.ZipFileで、ファイル名エンコーディングがUTF-8決めうちになってしまったようです。
従来のzipfile.ZipFile.writeは、zipに格納されるファイル名に8ビット文字列をそのまま使っていたため、エンコーディングを自分で選ぶことができました。
(とゆーか、ライブラリ側が関知するところではなかった(^^;))
しかし、Python3.0からはUNICODE文字列で与える形式となり、かつ今のところエンコーディングを変更することはできないみたい。 # ↑こうすると、Windowsでは解凍時にファイル名が文字化け。
# WindowsではShift_JIS(CP932)が一般的なので。
元々zipファイルはファイル名エンコーディングに問題を含んでいて、MacOSXで圧縮したzipをWindows側で解凍するとファイル名が文字化けするといったことが起きていたわけですけど、これがPython3.0で表面化してしまった感じですねー。
仕方ないので、zipfileを使っていたところをtarfileに置き換えて修正を進めてます。
標準がUNICODE文字列であることは実際便利で、今までエンコーディング変換で手間をかけていたところがすっきり書けるのは良いんですけど、しばらくは様々な問題が頻出しそうな予感がします。
Re:UNICODE文字列に起因する問題 (スコア:1)
Re: (スコア:0)
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で渡せってことだよね。
未確認だけどこれでできないの?
Re:UNICODE文字列に起因する問題 (スコア:2, 参考になる)
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)だけは正常に解凍できるという極悪仕様(^^;)
Re: (スコア:0)
いや、3.0でも同じですね。
ということは、仕様というよりは実装の問題ですから、言えばすぐに直されるんじゃないでしょうか。
Re:UNICODE文字列に起因する問題 (スコア:2, 参考になる)
ただ、現実問題として「すぐに直せる」レベルかどうかは少し微妙かもです。
ちょっと今は試せないんですが(作業が残っているため、まだ自宅マシンには導入できない(^^;))、3.0からは文字列がUNICODEになってしまった(8ビットの方はバイト列扱いのbytes型になった)ので、多分ですが中でエンコード/デコードが必要になってくると思われます。
現状だとファイル名エンコーディングを明示するインターフェースがZipFileに存在しないため、仕様を追加しないと対応は難しいんじゃないかと。
そもそもは現状の、「zip内ファイル名エンコーディングが環境依存」という状況が良くないんですよね……。
どのみちOSX等とのやり取りで支障を来しているので、私はこの際zipを捨ててtar.gzに移行する予定です(^^;)
Re: (スコア:0)
ないでしょうが、この手の問題は他にもいろいろな場面ででてきそうですね。
一つの対処法としてstrやbytesのメンバーとしてencodingを設定できるようにするのは
どうだろう。これなら意図したとおりに変換できるし、自動変換させればstrとbytesを
演算可能にもできる。
zipfileで非utf-8ファイル名のファイルを解凍するための最小限のハック (スコア:1, 参考になる)
+++ 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))
のは完全なミスでしょう。
あとはファイル名に関しては
filename = info.filename
else:
filename = info.filename.encode('cp437').decode('cp932')
今回3.0を使ってみて、bytesとstrの互換性の無さが気になった。
'abc'+b'123'やb'asd'.index('s')がエラーになるのは使いにくい。
Re: (スコア:0)
appnote [pkware.com]のAPPENDIX D - Language Encoding (EFS)に従っただけですね。確かに cp437 だけってのは互換性に対する配慮が足りないという気はしますが、Java の java.util.zip みたいにフラグも立てずに utf-8 で出力するよりはマシだと思います。
Re: (スコア:0)
Re: (スコア:0)
>ファイル名エンコーディングがUTF-8決めうちになってしまったようです。
それってjarファイルじゃないですか。
しかし、思ったのはやっぱりリリースされてから
試さない人がいるから、それなりの品質でもリリースしてしまった方がいいんだなぁ、ということ。
# MSはよく分かってる
raw string (スコア:3, 参考になる)
“「\」はraw文字列内において、常に字義通りに解釈されるようになった”
ぐらいがより正確なのではないかと。
rawでない普通の文字列リテラルでは当然「\u」が使えますので。
(じゃないと文字コード指定できないことに……)
Pythonでは文字列リテラルとしてraw文字列というものがあります。
リテラル中で「\」をエスケープさせたくないばやいに使うもので、文字列の前に r を付け加えることでraw文字列になります。
(正規表現の記述で重宝)
但し、2.6以前ではUNICODE16進指定のみ、文字コード指定であると解釈されるという実装になっていました。 これが、3.0以降からはUNICODE16進指定も無視され、raw文字列中の「\」は全てそのままの文字として出力されることになります。
実は (スコア:1)
水準3000
# 5文字までとかいやすぎ
Perl教徒としては (スコア:1)
# で、Perl6ってどうなるんだっけ?
Re:Perl教徒としては (スコア:2, 興味深い)
むしろPerlは後方互換性が今のところそれなりに確保されている点に賛辞を送りたい。
それゆえに抱えている問題はあるかもしれませんが、どんどん変わっていく言語ではコードを書く気になりません。
Perl6? 何それ? (笑
まぁとりあえず期待はしています。
Re:Perl教徒としては (スコア:2, 興味深い)
## がらくた折衷言語だろ?
python3.0は言語仕様の変更もさることながら、標準ライブラリの変更も大きい。
まぁ公式でもすぐに切り替えようという話ではないので、暫くは2.xでも問題ないな。
言語ではないところでは、Ubuntu HardyだとLANG=Cじゃないとコンパイルでこけるのはプチはまったけどね。
Re:Perl教徒としては (スコア:2, すばらしい洞察)
# 強調は引用者
シンプルに書かれた Perl は美しいと思いませんか。
Re:Perl教徒としては (スコア:5, おもしろおかしい)
同じ処理をするとして
・単純な処理を明快に積み重ねて20行で書かれた処理(理解するのに2分)
と
・変態じみた正規表現を駆使して2行で書かれた処理(理解するのに20分)
だと
後者を「シンプル」だと思ってしまうのがPerl教徒の恐ろしいところ
Re:Perl教徒としては (スコア:2, すばらしい洞察)
・おそらくその間のどこかが「シンプル」だろう
と思っているわけですが。
Re: (スコア:0)
Lisperによく見られる自虐なのか、本当に他の言語を知らないのか、判別がつかないんですが
たぶん例がよくないんでしょう
Re: (スコア:0)
http://parametron.blogspot.com/search/label/general%20problem%20solver [blogspot.com]
Re: (スコア:0)
Re:Perl教徒としては (スコア:1)
使いまわせるとこだと思います
pythonはただでさえ独自仕様が多くてとっつきにくいのに
前バージョンを踏襲さえしないのはどうかな
Re:Perl教徒としては (スコア:2, 興味深い)
> 使いまわせるとこだと思います
「今まで学習してきた言語知識」とはどの言語?
オブジェクト指向をJava辺りで学んだ身としては、Perlのオブジェクト指向には
どうにも馴染めなくて覚えるのをやめました。
Perlのよさは、手軽なテキスト処理と、豊富なライブラリ資産かなと思います。
今でもちょっとした(数十行程度の)スクリプトを書くならPerlが一番ですね。
一方で数万行を超えるような、きちんと設計して書くアプリケーションになると、
PythonやRubyのような言語のほうが自分にはなじみやすいです。
(最終的には慣れの問題だとは思いますけれども)
Re:Perl教徒としては (スコア:1)
冗談とPerlなりの真面目さの折衷なのです。たぶん。
オブジェクト指向なんつって、こんなもんでもできるだろっていう。
# ハッカー流ジョークとしては最高に面白い部類に入ると思ってます。実用的だし。
Re: (スコア:0)
最近ならPHPを足してもいいかな。
Re: (スコア:0)
#言語としてはシンプルだが、ポインタバグは悪夢。
C++?なにそれ?美味しいの?
Re: (スコア:0)
Java好きのWebプログラマはよくそんなことをいうけれど、
それぞれの言語なりの解決策はノウハウとしてあるとしても、マシン語での実装がイメージできるのに言語の制約でできなくて感じる理不尽な気分はポインタが生みだす災害を予防する努力よりもぐっと憂鬱です。
書くプログラムが低レベルか高レベルかによって、憂鬱に思う機会の多少が異なるのでアレですが。
Re: (スコア:0)
なるほどねえ
Cでの整数オーバーフローのハンドリングはイライラしますもんね
まだ移行したくない人は2.6系列を使いましょう (スコア:1, すばらしい洞察)
過去の資産は使える? (スコア:1)
# Djangoで遊び始めたのでそのへんも気になる
誤字指摘 (スコア:0)
リプレス(repress)は(欲求を)「抑止する」「抑圧する」
意図していたのはreplaceですね? [Y/y]
# いけないマコちゃんなのでAC
Pythonって専用セクションあるんだ (スコア:0)
命名元的に
ひ、ひどい (スコア:0)
いや、ほめ言葉なのか?
Re: (スコア:0)