More Related Content Similar to Python3 プログラミング勉強会 (20) More from Tetsuya Morimoto (16) Python3 プログラミング勉強会2. このスライドの注意事項/意図
●
基本的に Python3 を前提にこのスライドを作っています
●
Python3 の特徴について網羅できてはいません
– ググればすぐに見つかるようなものは省いた
●
文字列が全て Unicode になった
●
組み込み関数がジェネレーターを返すようになった
●
標準モジュール名やそのメソッドの命名規則が統一された
– Python2 から 3 への移行のノウハウはありません
– Python2 と 3 の両対応のノウハウはありません
Python3 でプログラミングするときに知っておくと
楽しそうなことを自分なりに調べてきた
がんばって調べたけど、間違ってたらごめんなさい
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
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 は見えないし
意識する必要もない
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 をメンテナンスするのはしんどい
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に
サンプルがたくさんある
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(...)
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()
コンテキストマネージャの定義
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
40. enum
●
PEP435 Adding an Enum type to the Python s
tandard library
– これも java から触発?と思ったけど違うかも?
– enumのドキュメントを読んでください
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 が
日常に忍び込んで欲しいですね。