Upload
takeshi-akutsu
View
196
Download
0
Embed Size (px)
Citation preview
2と3の違いから見るPythonの進化
辻 真吾(@tsjshg)
自己紹介
辻 真吾(1975年8月生まれ)
今は、東京大学先端科学技術研究センターで働いています
でも今年で任期が切れるので、引き続き転職先を模索中
近況:SoftwareDesign8月号に記事を書きました(そろそろ書店から消えてるかも)
今日の話題は
Pythonの基本的な文法や標準モジュールについて、2と3を比較しながら理解を深めることを目指します
(3.3は結構人気ですが、2系もまだまだ見かけるので)
目次
printと数値計算文字列クラスデータの保存(pickle)ジェネレータ式
基本
Python2.72系の最終バージョン2020年までサポート
Python3.4今後はこちらが進化
特に理由がなければ、3系がお勧めです
In [15]: #printは関数ですprint('test')
test
In [17]: #Python2では文としても表現出来ました(今はやらないほうがいいかも)print 'test'
test
In [3]: # Python3のprintは進化してます# Python2では次の1行で、Python3のprintと同等の機能を実現出来ます。from __future__ import print_function
In [6]: #改行したくない場合print('test',end='')
test
In [4]: #ちょっとしたプログレスバーimport timefor i in range(1,11): time.sleep(1) #何か時間のかかる処理 print('#'*i ,end='\r' if i < 10 else '\n')
##########
In [9]: # Python2では整数の割り算は切り捨てられます。3/2
Out[9]: 1
In [11]: from __future__ import division #Python3の機能をPython2で使うため3/2
Out[11]: 1.5
In [14]: # 切り捨てたいときは、//かmath.floorがあります。print(3//2)import mathprint(math.floor(3/2))
11.0
いよいよ文字列
分かりにくいと言われることも多いですが、3の考え方を基本にすれば大丈夫
In [20]: #まずは基本。引用符は単一でも二重でもprint('test')print("テスト")
testテスト
スクリプトに書くときは、ファイルの先頭から2行目までに特別なコメントを指定
# coding:utf-8
文字列でエラーを出したことがあってもなくても、これだけは覚えておこう
文字列をバイト列に暗号化(encode)と考えると分かりやすい(かも)
2と3でなぜ混乱するかというと
もちろんPython3の方が素直
In [37]: #Python2#普通に書くと、文字列という名のバイト列になるprint(len('test'))print(len('あ'))#Unicode文字列にはリテラルuが用意されているprint(len(u'あ'))
431
In [45]: #Python3#普通に書くと文字列print(len('あ'))print(len(u'あ')) #3.3からuを書いても無害
11
In [46]: # (Unicode)文字列をバイト列に変換(Python3)'あ'.encode('utf-8')
Out[46]: '\xe3\x81\x82'
In [50]: # バイト列を(Unicode)文字列に変換print(b'\xe3\x81\x82'.decode('utf-8'))
あ
In [4]: #Python2でよく見るエラー。'あ'.encode('utf-8')
---------------------------------------------------------------------------UnicodeDecodeError Traceback (most recent call last)<ipython-input-4-d88163347c1e> in <module>() 1 #Python2でよく見るエラー。----> 2 'あ'.encode('utf-8')
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe3 in position 0: ordinal not in range(128)
これ以上やると混乱しそうなので、このへんで。
Python3の方が、明らかにすっきりしているので、できればPython3で
クラスの進化でちょっと一息
In [4]: # Python2では2通りの方法があるclass OldStyle: passclass NewStyle(object): pass
_old = OldStyle()_new = NewStyle()
print(type(_old))print(type(_new))# Python3ではどちらも同じ
<type 'instance'><class '__main__.NewStyle'>
pickleモジュールを使うと、データを保存してあとで利用できます
In [10]: import picklemy_data = ([1,2,3], 'test')with open('data.pkl','wb') as f: pickle.dump(my_data,f)
In [11]: with open('data.pkl','rb') as f: my_data = pickle.load(f)print(my_data)
([1, 2, 3], 'test')
Python2ではpickleと、より高速なcPickleがあった
Python3ではpickleもジュールに統一
In [12]: # Python3のpickleの保存形式はPython2では読めないwith open('ver3.pkl','rb') as f: pickle.load(f)
---------------------------------------------------------------------------ValueError Traceback (most recent call last)
<ipython-input-12-856636e73365> in <module>() 1 # Python3のpickleの保存形式はPython2では読めない 2 with open('ver3.pkl','rb') as f:----> 3 pickle.load(f)
/Users/tsuji/anaconda/lib/python2.7/pickle.pyc in load(file) 1376 1377 def load(file):-> 1378 return Unpickler(file).load()
Python2で作ったファイルはPython3で読めるけど、文字列はUnicode文字列を使う
バイト列の文字列を使うとPython3で読み込んだときエラーになります
In [14]: # 関数型言語が流行っているので、map有名になってきましたmap(str, [1,2,3])
Out[14]: ['1', '2', '3']
In [5]: # Python3ではmapが関数ではなくデータ型。イテレータとして使えますmap(str, [1,2,3])
Out[5]: <map at 0x104955950>
In [6]: m = map(str, [1,2,3])next(m) # 遅延評価。一度にメモリを消費しない
Out[6]: '1'
In [8]: #リスト内包表記は便利だけど、リストが出来てしまう。[i**2 for i in range(4)]
Out[8]: [0, 1, 4, 9]
In [12]: # ジェネレータ式を使うと簡単にジェネレータが作れますg = (i**2 for i in range(4))print(next(g))print(next(g))print(next(g))print(next(g))# Python2ではg.next()と書けましたが、Python3ではnext(g)
0149
In [2]: # Python2では、rangeとxrangeがありました。# rangeはリストを生成し、xrangeは遅延評価に対応していました。range(3)
Out[2]: [0, 1, 2]
In [13]: # Python3ではrangeに統一され、リストは作られませんrange(3)
Out[13]: range(0, 3)
まとめ
Python3はよりシンプルに
文字列はUnicode文字列を使う
ジェネレータの利用を意識