Python3 プログラミング勉強会

  • 5,989 views
Uploaded on

 

More in: Engineering
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
5,989
On Slideshare
0
From Embeds
0
Number of Embeds
17

Actions

Shares
Downloads
9
Comments
0
Likes
8

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. Python3 プログラミング 2014-07-01 Tetsuya Morimoto
  • 2. このスライドの注意事項/意図 ● 基本的に Python3 を前提にこのスライドを作っています ● Python3 の特徴について網羅できてはいません – ググればすぐに見つかるようなものは省いた ● 文字列が全て Unicode になった ● 組み込み関数がジェネレーターを返すようになった ● 標準モジュール名やそのメソッドの命名規則が統一された – Python2 から 3 への移行のノウハウはありません – Python2 と 3 の両対応のノウハウはありません Python3 でプログラミングするときに知っておくと 楽しそうなことを自分なりに調べてきた がんばって調べたけど、間違ってたらごめんなさい
  • 3. 概要 ● きっかけ ● Python2 vs Python3 ● Python パッケージング ● (IMHO) Python プログラミング – Python のイディオム ● まとめ
  • 4. きっかけ
  • 5. unotools (1) ● unotools ( ゆーのつーるず ) – Python3 のみ対応 – OpenOffice.org/LibreOffice の UNO ( ゆーの ) を簡 単に使うためのライブラリ ● PyUNO のラッパーライブラリ – OpenDocument 形式を Python から簡単に扱う – まだアルファレベルだけど簡単なことはできる ● 初めて Python3 でコードを書いたら楽しかった この勉強会を開こうと思ったきっかけ
  • 6. unotools (2) ● 使い方/用途 – バッチ処理でのレポート生成 – OpenDocument から他のファイル形式へのフォーマット変換 ● 画像イメージ、 html 、 pdf など $ soffice --accept='socket,host=localhost,port=8100;urp;StarOffice.Service' $ python sample-scripts/calc-sample1.py -s localhost -d sample-scripts/datadir/ $ ls sample-calc.html sample-calc.pdf sample-calc_html_eaf26d01.png sample.csv sample.xls
  • 7. Python2 vs Python3
  • 8. どちらの Python バージョンを使ったら良い? ● 自分が選べるなら Python3 を選べば良い ● どっちを選んで良いのか分からなかったら Python3 を選べば良い ● 誰かが Python3 の移行が進んでないという 理由で Python2 を使おうと言ってたのなら それは無視すれば良い Python2 を使わないといけない理由がないなら 普通に Python3 を選べば良いと思う
  • 9. 但し Linux Distribution の事情は悩ましい ● クライアント向け – Ubuntu 14.04 LTS ● Python 2.7.6, Python 3.4.0 – Fedora 20 ● Python 2.7.5, Python 3.3.2 ● サーバー向け – RHEL/CentOS 5.x (サポート2017年3月31日まで) ● Python 2.4.x ● EPELが使えるならPython 2.6 ● IUS Community Projectが使えるならPython2.7, 3.1 – RHEL/CentOS 6.x (サポート2020年11月30日まで) ● Python 2.6.x ● IUS Community Projectが使えるならPython2.7, 3.2, 3.3 – RHEL/CentOS 7.x (サポート2024年6月30日まで) ● Python 2.7.x Python3 もインストールできるけど、 依然として Python2 も残っているし、 デフォルトは 2 を使うようになってる RHEL/CentOS は 2024 年まで Python2 が残る Python3 への移行を阻害している 1 つの要因でもある でも、これは大した問題ではない 標準リポジトリでは提供されないため Python3 を RPM で管理したいなら 外部リポジトリを使わないといけない 移行においては悩ましい課題 PEP373 コミュニティによる Python2.7 のサポートは 2020 年まで
  • 10. 別解 Python Distribution という概念 ● Using the Anaconda Python Distribution – Conda: Python-agnostic binary package manager ● Python はマルチプラットフォームに対応している ● Conda はクロスプラットフォームなパッケージマネージャー ● 複数の Python バージョンを切り替えたり、仮想環境にも対応 ● Conda は Anaconda (RHEL のインストーラー ) で使われるパッケージマネー ジャーを単体ツールとして切り出したもの – Continuum 社が Anaconda distributionを提供 ( 商用サービスもある ) ● PyPI にあるパッケージをミラーリングして Conda パッケージとして配布 ● バイナリディストリビューションとしても使える – Python2.7 または 3.4 を内包した Minicondaを Windows, MacOSX, Linux 向けに提供 Python 製のシステム向け ディストリビューションを配布する 誤解を恐れずに言えば、 パッケージマネージャーをインストールするついでに Python もインストールしちゃって それはユーザー ( システム管理者 ) から見えないから Conda 内で開発者が管理できる Conda 内で Python インタープリターは八百万の神様みたいな存在 agnostic( 不可知論 ) Conda は内部的に Python を使うけど、 Conda から Python は見えないし 意識する必要もない
  • 11. Python パッケージング
  • 12. Python のパッケージマネージャー That's a shame いままではそうだったんだけど、 Python3.4 から pip がデフォルトインストーラーになった https://twitter.com/gardaud/status/357638468572151808
  • 13. pip ● PEP453で pip が Python(3.4 から ) 本体に含まれ るようになった – --user オプションでホーム配下にパッケージをインス トールできる ● pip は厳密に言うとパッケージインストーラー – easy_install の不評 ● setuptools に含まれるパッケージインストーラー ● 初期のバージョンの頃から機能に対する悪評 ● アンインストール機能の欠如 – もともとは easy_install の置き換えを目的として発展
  • 14. コラム ~バージョンニング~ ● Python – major.minor.micro: 3.4.0 – PEP440 (PEP426から派生 ) ● [N:]N(.N)*[{a|b|c|rc}N][.postN][.devN] ● Author: Nick Coghlan, Status: Draft ● Epochはバージョンスキームが変わったときに使う ● Source labelは依存性解決などのツールのために使う ● 他のも見てみる – Semantic Versioning: major.minor.patch – Linux Kernel: major.minor.revision(patch) => 3.13.0-24 – Ruby: major.minor.teeny-patch => 1.9.3p545 ちょっと凝り過ぎ? 3 番目のバージョン番号の 呼び方はコミュニティによって違う
  • 15. パッケージング/パッケージ配布 (1) ● 2009 年頃から 2012 年頃までの事情 – パッケージングのこと知りたかったら清水川Webへ – 2009/12/05 distutils, setuptools, distribute, pip, virtualenv, buildout ● この頃を簡単に言うと ... – setuptools を多くの開発者が使うようになってた – ↑ メンテナンスされなくなって置き換えツールが乱立 – 「標準化へ向けて俺たちの戦いはこれからだ」だった ややこしいからね
  • 16. パッケージング/パッケージ配布 (2) ● 歴史的経緯 – 1998 標準ライブラリとしてdistutilsを提供 – 2000 distutilsの開発を中止 ● この後、開発者がdistutilsを使って自分で開発し始める – 2004 setuptoolsの開発が始まる ● 当時は開発が活発だった ● 依存関係の解決 ● Eggによるバイナリパッケージ配布 – 2009 distributeの開発をTarek Ziadéが始める ● メンテナンスされなくなったsetuptoolsを置き換えることが狙い ● setuptoolsの完全互換性を保持してメンテナンス再開、Python3対応も始める – 2012 distutils2の開発を中止 ● Python3.3でpackagingとして標準ライブラリ化予定だったが、中止になった – distutilsと同じ欠陥があった、コマンドベースの設計がいけてないとか – Windows向けのネイティブスクリプト実行やエントリーポイントの定義などが未サポート – 2013 [Distutils] Setuptools-Distribute merge announcement ● Setuptoolsとdistributeの統合を発表 (=> distributeの開発を中止) ● プロジェクトのゴールはsetuptoolsが "Obsolete" になること ● 次世代パッケージングの何かへ移行するまではメンテナンスを継続 – 2014 setuptools再び開発が活性化 ● Rapid Releaseな開発サイクルへ 成功を収めた packaging は放棄されたけど、 distutils を置き換える distlibへ setuptools で解決できてた setuptools のリリース履歴 setuptools 0.6c1 2006-07-20 setuptools 0.6c5 2007-01-09 setuptools 0.6c8 2008-02-15 setuptools 0.6c9 2008-09-24 Setuptools-Distribute merge announcement 2013-03-14 setuptools 0.6.41 2013-05-24 (distribute マージ ) setuptools 0.7 2013-06-02 setuptools 1.0 2013-08-18 ( 後方互換性を放棄 ) setuptools 2.0 2013-12-08 setuptools 3.0 2014-03-04 setuptools 4.0 2014-06-02 setuptools 5.0 2014-06-15 setuptools 5.2 2014-06-23 ( 最新 ) Python2.4 Python2.0 Python2.7, 3.3 Python2.6, 3.0 Python2.7, 3.4 setuptools の原罪と 罪贖
  • 17. パッケージング/パッケージ配布 (3) ● パッケージングと pbr – Python Build Reasonableness が名前の由来 – setuptools を拡張するツール ● ビルドとデプロイを簡単にすることが目的 – git tag やリビジョンからバージョンを自動生成 – git log から AUTHORS と ChangeLog を自動生成 – スマートなパッケージファイル探索 – requiremetns.txt から依存関係を解決 – Sphinx でドキュメントを生成 ● distutils2 由来のパッケージのメタデータを setup.cfg として使う – 宣言型の設定ができる ● テストランナーに toxと testrを使う – tox はテストのために仮想環境を構築して、インストール、依存関係の解決、テストを実行 – testr はテスト結果を追跡するためのツール (testrepository のテストランナー ) ● tox で作った仮想環境に入って失敗したテストを再現させたり、デバッグしたりできるらしい – OpenStackプロジェクトがメンテナンスしてるから安心? git と連携したパッケージ作成 PEP426 Metadata 2.0 フォーマットを定義
  • 18. パッケージング/パッケージ配布 (4) ● そして wheel フォーマットへ – Python の公式ディストリビューションフォーマットがなかった – setuptools が導入した egg フォーマットはあったが ... ● zip アーカイブ内にパッケージ情報が付いてる ● pip が egg を扱えない ( これまでは sdist のみだった ) ● egg はインポート可能なフォーマット – PEP427で公式フォーマット wheel を定義 ● やっぱりアーカイブは zip フォーマット ● pip でも扱える ● whl はインストールのためのフォーマット – パッケージングのこと知りたかったら @aodagへ ● パッケージングの今と未来 – Python2.x/3.x 両対応のパッケージングとか ● Python 2.5 からPython 3.3 で 動作するツールの作り方 Python のパッケージングで ググったらこの 2 人がヒットする 拡張子は .whl Metadata 2.0 やパッケージ構造が PEP のそれと非互換? java の jar ファイルのようなもの?
  • 19. コラム ~メンテナンス~ ● 自分が作ったパッケージが世界中で広く使われるようになった – 最初のうちは やがてメンテナンスに� � – たびたびそういうのは発生する ● setuptools 然り、 MySQL-Python 然り ● Python 3 Readiness – MySQL-Python も Python3 対応が望まれていた ... ● Python_3_の_MySQL_ドライバ事情 ● MySQL-python の Python 3 対応 ● mysqlclient をリリースしました ● メンテナーに権限を移譲しよう – 1 人でずっと OSS をメンテナンスするのはしんどい
  • 20. (IMHO)Python プログラミング
  • 21. Python が大事にしている概念 ● TOOWTDI (There's Only One Way To Do IT) – やり方はたった 1つでいい ● Pythonic とは – 小さなコードパターンに最も効率的なイディオムを使ったコーディングや構文 – Code Like a Pythonista: Idiomatic Python – The Hitchhiker’s Guide to Python! ● The Zen of Python (PEP20) – Beautiful is better than ugly. ( 汚いよりきれい方が良い) – Explicit is better than implicit. ( 暗黙的よりも明示的な方が良い ) – Although practicality beats purity. ( とはいえ、純粋さよりも実用的であること ) ● The number one thing that Python programmers do is read code. – コードは書かれるよりも読まれることの方が多い そんな Python であっても、 コーディングやそのイディオムは同じであっても、 設計の在り方は個々のプログラマーによって違う 人それぞれに設計スタイルが違うの当然で、全体で一貫性があれば良いと思う Python のイディオムを知ろう 他人のコードを読んでいて 気になるのは Pythonic じゃないコード、 つまりはそのイディオムが共有されてないとき PEP8 の一節 "A Foolish Consistency is the Hobgoblin of Little Minds" また、このバランスも難しい
  • 22. デコレーター ● 動的に関数やクラスを拡張するための構文 – GoF の Decorator patternとは厳密には違うみたい – 関数ラッピングの可読性を上げる狙い – 簡潔に書けるからよく使われる ● デコレートの用途 – 引数チェック – キャッシュ – プロキシ – コンテキストプロバイダー 但し、デコレーターでラップする 関数の返り値を変えたりするのはよくない PythonDecoratorsに サンプルがたくさんある
  • 23. functools.singledispatch ● PEP443 Single-dispatch generic functions – プロキシデコレーターのひとつ – Common Lisp Object System から触発? – 汎用関数を作るための仕組み
  • 24. サンプルコード from functools import singledispatch @singledispatch def judge(type_): raise NotImplementedError('unknown type: {}'.format(type_)) @judge.register(int) def int_type(num): print('I am integer: {}'.format(num)) @judge.register(list) def list_type(sequence): print('I am list: {}'.format(sequence)) def main(): judge(1) judge([2, 3]) judge('test') 汎用関数 judge の第一引数の型でディスパッチ # これまでのパターン # 汎用関数に isinstance を使う def judge(data): if isinstance(data, int): return int_type(data) elif isinstance(data, list): return list_type(data) else: raise NotImplementedError(...)
  • 25. functools.lru_cache ● @functools.lru_cache(maxsize=128, typed=False) – 関数の結果を LRU (latest recently used) キャッ シュで保持するデコレーター – メモ化などに使うと便利
  • 26. サンプルコード from functools import lru_cache @lru_cache(maxsize=None) def memoize_fib(n): """ >>> [memoize_fib(n) for n in range(16)] [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610] >>> memoize_fib.cache_info() CacheInfo(hits=28, misses=16, maxsize=None, currsize=16) """ if n < 2: return n return memoize_fib(n-1) + memoize_fib(n-2) In [1]: from lru_cache_sample1 import fib, memoize_fib In [2]: timeit -n 3 [fib(n) for n in range(20)] 3 loops, best of 3: 6.49 ms per loop In [3]: timeit -n 3 [memoize_fib(n) for n in range(20)] 3 loops, best of 3: 36.2 µs per loop IPython を使うとパフォーマンスを比較するのが簡単
  • 27. with 文と contextlib ● PEP343 The "with" statement – Lisp でよく使われた with-* マクロから触発? – コンテキストマネージャーと一緒に使う ● contextlibを使うと便利 ● グローバル情報の保存/更新 ● リソースのロック/アンロック ● ファイルのオープン/クローズ with open('test.txt') as f: first, *rest, last = f.readlines() f = open('test.txt') try: first, *rest, last = f.readlines() finally: f.close()
  • 28. サンプルコード from contextlib import contextmanager @contextmanager def my_open(filename): f = open(filename) try: yield f finally: f.close() class MyContextManager: def __init__(self, filename): self.filename = filename self.file = None def __enter__(self): self.file = open(self.filename) return self.file def __exit__(self, type, value, traceback): if type is not None: self.file.close() コンテキストマネージャの定義
  • 29. ジェネレーター ● イテレーターやコルーチンを実装するための仕組み ● itertoolsはイテレーターを扱ったり、 ジェネレーターを作るツールのライブラリ – APL, Haskell, SML から触発されてる – 高速、省メモリ、 iterable を受け取ってイテレー ターを返す
  • 30. サンプルコード def read_file(filename): """ ファイルを1行ずつ読み込んで返す >>> list(read_file('test.txt')) ['1', '2', '3', '4', '5'] """ with open(filename) as f: for line in f: yield line.strip() def read_file_with_int(filename): """ >>> list(read_file_with_int('test.txt')) [1, 2, 3, 4, 5] """ return map(int, read_file(filename)) def read_file_with_int_gc(filename): """ >>> list(read_file_with_int_gc('test.txt')) [1, 2, 3, 4, 5] """ return (int(x) for x in read_file(filename)) ジェネレーターを作成する には yield を使うだけ イテレーターと高階関数を組み合わせると簡潔になる? def read_file_with_power(filename, num): """ >>> from itertools import repeat >>> list(map(pow, read_file_with_int('test.txt'), repeat(3))) [1, 8, 27, 64, 125] >>> list(read_file_with_power('test.txt', 3)) [1, 8, 27, 64, 125] """ from itertools import repeat return map(lambda x, y: pow(int(x), y), read_file(filename), repeat(num)) map とジェネレーター内包表記 どちらでも 好みで良い
  • 31. ジェネレーターを使った移譲 ● PEP380 Syntax for Delegating to a Subgenerator – PEP342で yield を式として扱えるようになった ● send: ジェネレーターに値を渡す ● throw: ジェネレーターに例外を発生させる ● close: ジェネレーターを終了させる – これらをサブジェネレーターで扱うのが大変
  • 32. サンプルコード def read_file_with_end(filename): """ >>> list(read_file_with_end('test.txt')) ['1', '2', '3', '4', '5', 'end'] """ for line in read_file(filename) yield line yield 'end' def read_file_with_type(filename): """ >>> g = read_file_with_type('test.txt') >>> next(g) 'start' >>> g.send(int) 1 """ type_ = yield 'start' with open(filename) as f: for line in f: type_ = yield type_(line.strip()) ジェネレーターで値を生成 するだけなら移譲は簡単 yield from を使うと値が渡せる ジェネレーターへの移譲も簡単 def read_file_with_send(filename): """ >>> g = read_file_with_send('test.txt') >>> next(g) 'start' >>> list(map(g.send, [int, str, list, tuple, bool])) [1, '2', ['3'], ('4',), True] >>> next(g) 'end' """ yield from read_file_with_type(filename) yield 'end'
  • 33. Python の保守的コーディング ● つい後方互換性を気にしてコードを書きがち – Python2.4 (RHEL/CentOS 5.x があると辛い ) はオワコン ● functools や with 文と contextlib は Python2.4 で使えない ● ジェネレーターは yield 文のみ – try … finally から yield 使えない ● try … except … finally も書けない ● operator.itemgetter/attrgetter で複数の引数を取れない ● r = True if condition else False も書けない – 小さなコードパターンを扱うライブラリは揃ってきている が、 2.4 を考慮して使えないことが多い ● Python3 はこれらが使い放題 → 書いてて楽しい 他にも 2.4 でできないことがある 2.4 のことを考えながら コーディングするのはもううんざり その次は 2.6 で、 これも直に辛くなる ...
  • 34. データ構造とアルゴリズム ● 集合型 set の応用例 – 集合演算使うと処理が簡潔になることがある def has_invalid_fields_loop(fields): for field in fields: if field not in ['foo', 'bar']: return True return False def has_invalid_fields_set(fields): return bool(set(fields) - set(['foo', 'bar'])) ループがなくなった! 上の方が意図は分かりやすい? 下の方がコードが簡潔?
  • 35. super を使った処理の移譲 ● Python Is Not Java – ここにある話題じゃないけど、多重継承もその 1 つ ● Python’s super() considered super! – super はスーパーだという話 – Python の多重継承は移譲の仕組みを提供 ● MRO(Method Resolution Order): C3線形化アルゴリズム ● MRO の仕組みを知っていれば後から移譲先を変更できる ● 既存のコードをいじらない → コードが安定する
  • 36. サンプルコード >>> class A: ... def f(self): ... print('A') >>> class B(A): ... def f(self): ... print('B') ... super().f() >>> class C(B): pass >>> C.mro() [<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>] >>> C().f() B A >>> class D(A): ... def f(self): ... print('D') >>> class E(C, D): pass >>> E.mro() [<class '__main__.E'>, <class '__main__.C'>, <class '__main__.B'>, <class '__main__.D'>, <class '__main__.A'>, <class 'object'>] >>> E().f() B D B.f メソッドで呼び出す super が D.f に変更された! A B C D E 1 3 2 4 5 object 6
  • 37. コラム 〜 unicode 文字列〜 ● 文字列が全部 Unicode になった – 見た目が文字の Unicode は変数として使える >>> π = 3.14 >>> λ = lambda x: x ** 2
  • 38. java から学んだもの
  • 39. concurrent.futures ● PEP 3148: The concurrent.futures module – java.util.concurrent から触発されたモジュール – Executor でスレッド/プロセス実行を制御する 高レベルインターフェースを提供
  • 40. enum ● PEP435 Adding an Enum type to the Python s tandard library – これも java から触発?と思ったけど違うかも? – enumのドキュメントを読んでください
  • 41. まとめ ● Python3 すごいよ、楽しいよ – 後方互換性を気にせずコーディングできる楽しさ – 小さなコードパターンを扱う言語機能や標準ライブ ラリが整ってきて、関数型プログラミングっぽい簡 潔なコードが書きやすくなった – Python3 対応のライブラリも十分揃ってる ● これからは Python3 を使おう
  • 42. 中級者向け ● このスライドの内容が面白かったら ... – The Hacker's Guide to Python ( 英語 ) 読むと良い ● 2014-03 に出版されたばかりだから内容が新しい ● 本スライドでも多くの内容を参考にして引用しました コーディング前に ドキュメントを書くというのは、 実装の詳細をコミットしないで その機能やワークフローを じっくり考え抜くことになり得る、 というのも分かった https://julien.danjou.info/books/the-hacker-guide-to-python
  • 43. 日本語で技術書を読みたい人向け ● 英語を読むのが辛かったら ... – エキスパート Python プログラミングを買うと良い ● 原著 2008-09 出版、 2010-05-31 翻訳 ● 基本的に Python2.x 向けなのでさすがに内容は古い – それでも Python でのアプリ開発の要点は掴める – 付録 A の Unicode の章は本書オリジナルでよくはまるところ ● 日本で初めて発売された Python 中級者向けの技術書 – この本が売れれば The Hacker's Guide to Python が 翻訳される可能性も高くなる? – 読まなくても買うと未来につながるかも? http://ascii.asciimw.jp/books/books/detail/978-4-04-868629-7.shtml ステマ 半分冗談だよ!
  • 44. 初心者向け ● このスライドの内容が難しかったら ... – パーフェクト Python 読むと良い ● Python の禅を全て解説している ● 言語仕様、ライブラリ、応用範囲まで一通り網羅 http://gihyo.jp/book/2013/978-4-7741-5539-5 ステマ Python は比較的に言語仕様が シンプルで,学習が容易です。 ( 中略 ) 今年はへび年なので, こっそりと Python が 日常に忍び込んで欲しいですね。
  • 45. その他に参考にしたもの ● そうだ!EuroPython2011へ行こう ● 「PyCon US 2012」 イベントレポート ● Key differences between Python 2.7.x and Py thon 3.x ● 10 awesome features of Python that you can' t use because you refuse to upgrade to Pyth on 3