40
2 3 Python @tsjshg

S03 t2 sta_py_tsuji_0810_slides

Embed Size (px)

Citation preview

Page 1: S03 t2 sta_py_tsuji_0810_slides

2と3の違いから見るPythonの進化

辻 真吾(@tsjshg)

Page 2: S03 t2 sta_py_tsuji_0810_slides

自己紹介

辻 真吾(1975年8月生まれ)

今は、東京大学先端科学技術研究センターで働いています

でも今年で任期が切れるので、引き続き転職先を模索中

近況:SoftwareDesign8月号に記事を書きました(そろそろ書店から消えてるかも)

Page 3: S03 t2 sta_py_tsuji_0810_slides

今日の話題は

Pythonの基本的な文法や標準モジュールについて、2と3を比較しながら理解を深めることを目指します

(3.3は結構人気ですが、2系もまだまだ見かけるので)

Page 4: S03 t2 sta_py_tsuji_0810_slides

目次

printと数値計算文字列クラスデータの保存(pickle)ジェネレータ式

Page 5: S03 t2 sta_py_tsuji_0810_slides

基本

Python2.72系の最終バージョン2020年までサポート

Python3.4今後はこちらが進化

特に理由がなければ、3系がお勧めです

Page 6: S03 t2 sta_py_tsuji_0810_slides

In [15]: #printは関数ですprint('test')

test

Page 7: S03 t2 sta_py_tsuji_0810_slides

In [17]: #Python2では文としても表現出来ました(今はやらないほうがいいかも)print 'test'

test

Page 8: S03 t2 sta_py_tsuji_0810_slides

In [3]: # Python3のprintは進化してます# Python2では次の1行で、Python3のprintと同等の機能を実現出来ます。from __future__ import print_function

Page 9: S03 t2 sta_py_tsuji_0810_slides

In [6]: #改行したくない場合print('test',end='')

test

Page 10: S03 t2 sta_py_tsuji_0810_slides

In [4]: #ちょっとしたプログレスバーimport timefor i in range(1,11): time.sleep(1) #何か時間のかかる処理 print('#'*i ,end='\r' if i < 10 else '\n')

##########

Page 11: S03 t2 sta_py_tsuji_0810_slides

In [9]: # Python2では整数の割り算は切り捨てられます。3/2

Out[9]: 1

Page 12: S03 t2 sta_py_tsuji_0810_slides

In [11]: from __future__ import division #Python3の機能をPython2で使うため3/2

Out[11]: 1.5

Page 13: S03 t2 sta_py_tsuji_0810_slides

In [14]: # 切り捨てたいときは、//かmath.floorがあります。print(3//2)import mathprint(math.floor(3/2))

11.0

Page 14: S03 t2 sta_py_tsuji_0810_slides

いよいよ文字列

分かりにくいと言われることも多いですが、3の考え方を基本にすれば大丈夫

Page 15: S03 t2 sta_py_tsuji_0810_slides

In [20]: #まずは基本。引用符は単一でも二重でもprint('test')print("テスト")

testテスト

Page 16: S03 t2 sta_py_tsuji_0810_slides

スクリプトに書くときは、ファイルの先頭から2行目までに特別なコメントを指定

# coding:utf-8

Page 17: S03 t2 sta_py_tsuji_0810_slides

文字列でエラーを出したことがあってもなくても、これだけは覚えておこう

文字列をバイト列に暗号化(encode)と考えると分かりやすい(かも)

Page 18: S03 t2 sta_py_tsuji_0810_slides

2と3でなぜ混乱するかというと

もちろんPython3の方が素直

Page 19: S03 t2 sta_py_tsuji_0810_slides

In [37]: #Python2#普通に書くと、文字列という名のバイト列になるprint(len('test'))print(len('あ'))#Unicode文字列にはリテラルuが用意されているprint(len(u'あ'))

431

Page 20: S03 t2 sta_py_tsuji_0810_slides

In [45]: #Python3#普通に書くと文字列print(len('あ'))print(len(u'あ')) #3.3からuを書いても無害

11

Page 21: S03 t2 sta_py_tsuji_0810_slides

In [46]: # (Unicode)文字列をバイト列に変換(Python3)'あ'.encode('utf-8')

Out[46]: '\xe3\x81\x82'

Page 22: S03 t2 sta_py_tsuji_0810_slides

In [50]: # バイト列を(Unicode)文字列に変換print(b'\xe3\x81\x82'.decode('utf-8'))

Page 23: S03 t2 sta_py_tsuji_0810_slides

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)

Page 24: S03 t2 sta_py_tsuji_0810_slides

これ以上やると混乱しそうなので、このへんで。

Python3の方が、明らかにすっきりしているので、できればPython3で

Page 25: S03 t2 sta_py_tsuji_0810_slides

クラスの進化でちょっと一息

Page 26: S03 t2 sta_py_tsuji_0810_slides

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'>

Page 27: S03 t2 sta_py_tsuji_0810_slides

pickleモジュールを使うと、データを保存してあとで利用できます

Page 28: S03 t2 sta_py_tsuji_0810_slides

In [10]: import picklemy_data = ([1,2,3], 'test')with open('data.pkl','wb') as f: pickle.dump(my_data,f)

Page 29: S03 t2 sta_py_tsuji_0810_slides

In [11]: with open('data.pkl','rb') as f: my_data = pickle.load(f)print(my_data)

([1, 2, 3], 'test')

Page 30: S03 t2 sta_py_tsuji_0810_slides

Python2ではpickleと、より高速なcPickleがあった

Python3ではpickleもジュールに統一

Page 31: S03 t2 sta_py_tsuji_0810_slides

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()

Page 32: S03 t2 sta_py_tsuji_0810_slides

Python2で作ったファイルはPython3で読めるけど、文字列はUnicode文字列を使う

バイト列の文字列を使うとPython3で読み込んだときエラーになります

Page 33: S03 t2 sta_py_tsuji_0810_slides

In [14]: # 関数型言語が流行っているので、map有名になってきましたmap(str, [1,2,3])

Out[14]: ['1', '2', '3']

Page 34: S03 t2 sta_py_tsuji_0810_slides

In [5]: # Python3ではmapが関数ではなくデータ型。イテレータとして使えますmap(str, [1,2,3])

Out[5]: <map at 0x104955950>

Page 35: S03 t2 sta_py_tsuji_0810_slides

In [6]: m = map(str, [1,2,3])next(m) # 遅延評価。一度にメモリを消費しない

Out[6]: '1'

Page 36: S03 t2 sta_py_tsuji_0810_slides

In [8]: #リスト内包表記は便利だけど、リストが出来てしまう。[i**2 for i in range(4)]

Out[8]: [0, 1, 4, 9]

Page 37: S03 t2 sta_py_tsuji_0810_slides

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

Page 38: S03 t2 sta_py_tsuji_0810_slides

In [2]: # Python2では、rangeとxrangeがありました。# rangeはリストを生成し、xrangeは遅延評価に対応していました。range(3)

Out[2]: [0, 1, 2]

Page 39: S03 t2 sta_py_tsuji_0810_slides

In [13]: # Python3ではrangeに統一され、リストは作られませんrange(3)

Out[13]: range(0, 3)

Page 40: S03 t2 sta_py_tsuji_0810_slides

まとめ

Python3はよりシンプルに

文字列はUnicode文字列を使う

ジェネレータの利用を意識