python4phper - phpユーザのためのpython入門 (python2.5)

218
日付 PHP ユーザのための Python 入門 Python4PHPer 08回講習会 2010-10-03(Sun) 1

Upload: kwatch

Post on 14-May-2015

5.595 views

Category:

Technology


0 download

DESCRIPTION

PHPユーザのためのPython入門です。PHPのコードとPythonのコードを並べて書いてるので、PHPユーザにとっては学習しやすいと思います。なお昔の資料なので、Pythonのバージョンが2.5であることに注意。

TRANSCRIPT

Page 1: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

日付

PHPユーザのためのPython入門Python4PHPer 第08回講習会 2010-10-03(Sun)

1

Page 2: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

概要と特徴

2

Page 3: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

概要✤ 動的なスクリプト言語✤ 世界中で人気(特にヨーロッパ)✤ 作者:Guido van Rossum(Google)✤ http://www.python.org/

3

Page 4: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

長所✤ 簡潔な言語仕様と読みやすい構文✤ 強力な機能と豊富なライブラリ✤ 豊富なドキュメント(日本語訳あり)✤ 組織立った開発&明確なスケジュール✤ Windowsを公式にサポート

4

Page 5: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

実績✤ YouTube(Webサイト全般)✤ Google(社内システム、Google AppEngine)✤ RedHat Linux (インストーラ, パッケージ管理システム)✤ Maya (ハイエンド3DCGソフト)✤ Blender (3Dモデリング・レンダリングソフト)✤ ERP5 (基幹業務パッケージ)✤ BitTorrent (P2P通信ソフト)✤ Skencil (ドローソフト)✤ Mercurial, Bazaar (バージョン管理システム)✤ 他多数

✤ http://www.python.org/about/success/✤ http://ja.wikipedia.org/Pythonを使っている製品あるいはソフトウェアの一覧

5

Page 6: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

特徴(対PHP)✤ 見た目がきれい

✤ インデントを使った構文(見た目=意味)✤ 行末の「;」がいらない✤ 「$var」ではなく「var」✤ 「$this->method()」ではなく「self.method()」✤ 「array(10,20,30)」ではなく「[10, 20, 30]」✤ 「array('one'=>1)」ではなく「{'one':1}」

6

Page 7: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

特徴(対PHP)✤ 本格的な言語仕様

✤ オブジェクト指向 (多重継承あり、インターフェースなし)✤ 関数オブジェクト、クロージャ✤ 例外機能 (finallyあり)✤ 名前空間(パッケージ、モジュール)✤ イテレータ、ジェネレータ

7

Page 8: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

特徴(対PHP)✤ その他

✤ 汎用言語 (Webアプリに限定されない)✤ 配列と辞書とが別のデータ構造✤ インタラクティブシェルが標準機能✤ JavaScripと類似点が多い✤ 他の人からバカにされない✤ 国内では仕事がない

8

Page 9: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

日本語ドキュメント✤ Python和訳ドキュメント

✤ http://www.python.jp/doc/  (ダウンロードするなら「Windows Help (chm)」がオススメ)

✤ 主要ドキュメント: チュートリアル、ライブラリリファレンス、言語仕様リファレンス

✤ コーディング規約✤ PEP 8: Style Guide for Python Code (日本語訳)

http://oldriver.org/python/pep-0008j.html

✤ Google Python スタイルガイド(日本語訳)http://works.surgo.jp/translation/pyguide.html

9

Page 10: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

インストールと起動

10

Page 11: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

Windows

✤ http://www.python.org/download/releases/2.5.4/ から「python-2.5.4.msi」をダウンロードしてインストール✤ 標準では C:\Python25 にインストールされる✤ 環境変数 %PATH% に C:\Python25 を追加するとよい例: set PATH=%PATH%;C:\Python25

✤ PyScripter(Python用IDE)をインストール http://mmm-experts.com/Products.aspx?ProductId=4  から左メニューの「Download」をクリック

注: Google AppEngine が 2.5 系のため、本稿では 2.5 系列を使う

11

Page 12: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

MacOS X

✤ 標準で Python がインストール済み(だけど、バージョンが違う)

✤ MacPorts でインストール

✤ $HOME/.bashrc に「alias py=python」を追加

注: Google AppEngine が 2.5 系のため、本稿では 2.5 系列を使う

$ sudo port install python 25$ sudo python_select python25$ which python/opt/local/bin/python$ python -VPython 2.5.4

12

Page 13: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

自前でコンパイル$ wget http://www.python.org/ftp/python/2.5.5/Python-2.5.5.tar.bz2$ tar xjf Python-2.5.5.tar.bz2$ cd Python-2.5.5$ ./configure --prefix=/usr/local/python/2.5.5$ make$ sudo make install$ export PATH=/usr/local/python/2.5.5/bin:$PATH$ which python /usr/local/python/2.5.5/bin/python$ alias py=python$ cat >> $HOME/.bashrcexport $PATH=/usr/local/python/2.5.5/bin:$PATHalias py=python^D

注: Google AppEngine が 2.5 系のため、本稿では 2.5 系列を使う

13

Page 14: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

起動

$ python example.py # または py example.py

スクリプト名を指定して起動

$ python # または py

>>> 1 + 12>>> exit() # または Control+D

スクリプト名を指定せずに起動(インタラクティブシェル)

または

$ ipython # より高機能なインタラクティブシェル

14

Page 15: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

エラーがあったら

>>> name = "Haruhi">>> namaeTraceback (most recent call last): File "<stdin>", line 1, in <module>NameError: name 'namae' is not defined

•エラーが発生したら、いちばん下のメッセージを見ること

ファイル名と行番号

例外クラスとエラーメッセージ

15

Page 16: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

主な例外クラス✤ SyntaxError : 文法が間違っている、またはコードに日本語が含まれて

いるのに「# -*- coding: utf-8 -*-」がない✤ NameError : 変数名や関数名を間違えている✤ TypeError : データや引数の数または型が間違っている✤ ValueError : 型は正しいが値として間違っている✤ AttributeError : 属性名やメソッド名を間違えている、

または変数の値がNoneである✤ UnicodeEncodeError : ユニコード関連のエラー✤ KeyError : 辞書のキーが存在しない✤ IndexError : リストやタプルで添字が範囲外✤ IOError : ファイルが存在しない、またはアクセス許可がない✤ ImportError : モジュール名を間違えている

16

Page 17: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

サンプルプログラム

【関連ドキュメント】

• チュートリアル: 3. 形式ばらない Python の紹介http://www.python.jp/doc/release/tut/node5.html

17

Page 18: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

コメントPHP Python

// 行コメント# 行コメント/* 範囲コメント */

# -*- coding: utf-8 -*-# 行コメント

•「#」が行コメント•範囲コメントはなし•日本語を含める時はマジックコメントが必要

•「//」と「#」が行コメント

•「/* */」が範囲コメント

マジックコメント(「# coding: utf-8」でも可)

18

Page 19: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

Hello WorldPHP Python

echo "Hello World!\n"; print "Hello World!"# またはimport syssys.stdout.write( "Hello World!\n")

•「;」が必要ない• print が自動的に改行を出力

•文末に「;」が必要•改行を出力するには「\n」を明示

19

Page 20: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

Hello World (2)PHP Python

$name = "World";echo "Hello ", $name, "!\n";echo "Hello $name!";

name = "World"print "Hello", name, "!"print "Hello %s!" % name

•変数に $ をつける•文字列中に変数を埋め込める

•変数に prefixをつけない•文字列中に変数を埋め込めない

20

Page 21: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

奇数だけ出力PHP Python

$arr = array(1, 2, 3, 4, 5);foreach ($arr as $item) { if ($item % 2 == 1) { echo $item, "\n"; }}

list1 = [1, 2, 3, 4, 5]for item in list1: if item % 2 == 1: print item

•配列はarray()• foreach や if で () が必要 •ブロックは「{ }」で表現

•リストは []• for や if で () いらず •ブロックは「:」とインデントで表現

21

Page 22: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

フィボナッチ数列PHP Python

function fib($n) { return $n <= 2 ? 1 : fib(n-1) + fib(n-2);}echo fib(30);

def fib(n): return 1 if n <=2 else \ fib(n-1) + fib(n-2)

print fib(30)

•関数定義は「function」•条件演算子は

式 ? 真のとき : 偽のとき

•関数定義は「def」•条件演算子は真のとき if 式 else 偽のとき

22

Page 23: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

データの中身を表示PHP Python

$val = array( "one"=>1, "two"=>2);var_export($val);

val = { "one":1, "two": 2 }print repr(val)

•連想配列はarray()•データの中身は

var_export() や var_dump() で表示

•辞書は { }•データの中身は repr() で表現 (なしでもよい)

23

Page 24: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

メタプログラミングPHP Python

function errmsg($mesg) { $f = fopen("php://stderr", "w"); fwrite($f, $mesg."\n"); fclose($f);}$func = 'errmsg';$func("ERROR");

import syssys.stderr.write("ERROR\n")write = sys.stderr.writewrite("ERROR\n")

x = 1add1 = x.__add__print add1(3) #=> 4

•メソッドを取り出し、変数に代入可能、かつ呼び出し可能

•関数名やメソッド名を表す文字列を変数に代入し、呼び出し可能

24

Page 25: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

リテラル

【関連ドキュメント】

• 言語仕様リファレンス: 2.4 リテラル (literal)http://www.python.jp/doc/release/ref/literals.html

• ライブラリリファレンス: 3. 組み込み型http://www.python.jp/doc/release/lib/types.html

25

Page 26: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

数値PHP Python

123 # 整数077 #=> 63 0xFF #=> 255 3.14 # 小数1.0e-4 #=> 0.0001 

pow(2,64) #=> 1.844674407371E+19 

123 # 整数077 #=> 63 0xFF #=> 255 3.14 # 小数1.0e-4 #=> 0.0001 3+4j # 複素数2**64 #=> 18446744073709551616L 

26

Page 27: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

文字列PHP Python

# メタキャラクタ解釈あり"str\n"

# メタキャラクタ解釈なし'str\n'

# メタキャラクタ解釈あり"str\n"'str\n'

# メタキャラクタ解釈なしr"str\n"r'str\n'

27

Page 28: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

複数行文字列PHP Python

# 複数行文字列"aaabbbccc"

'aaabbbccc'

# 複数行文字列"""aaabbbccc"""

r'''aaabbbccc'''

「"」3つまたは「’」3つで囲む

「r」をつけることも可

28

Page 29: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

ヒアドキュメントPHP Python

# ヒアドキュメント$string = <<<ENDaaabbbcccEND;

# ヒアドキュメントはなし、# 複数行文字列を使うstring = """aaabbbccc"""[1:]

最初の改行文字を取り除く(詳細は後述)

29

Page 30: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

ユニコードPHP Python

# 該当機能なし # -*- coding: utf-8 -*-

"ばけらった" # stru"ばけらった" # unicode

## 変換u"ば".encode('utf8') # str"ば".decode('utf8') # unicode

マジックコメント

•マジックコメントがないとSyntaxError

•「# coding: utf-8」でも可30

Page 31: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

真偽値、NULLPHP Python

TRUE # 真FALSE # 偽NULL # NULL

True # 真False # 偽None # NULL

•大文字・小文字の区別なし•偽となるのは FALSE, NULL,

0, 空の文字列や配列

•大文字・小文字の区別あり•偽となるのは False, None, 0, 空の文字列やリストやタプルや辞書

31

Page 32: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

演算子

【関連ドキュメント】

• 言語仕様リファレンス: 5. 式 (expression)http://www.python.jp/doc/release/ref/expressions.html

• ライブラリリファレンス: 3. 組み込み型http://www.python.jp/doc/release/lib/types.html

32

Page 33: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

同値判定PHP Python

"123" == "123""123" != "123" "0123" == 123 #=> TRUE"0123" === 123 #=> FALSE"0123" === "123" "0123" !=== "123"

"123" == "123""123" != "123""123" == 123 #=> False"123" != "123" u"123" == "123" #=> True

• '==' は文字列が数値に変換されることがある

• '===' は変換せずに比較

•数値と文字列が勝手に変換されることはない

• unicodeは変換される

33

Page 34: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

同一判定Python

True == 1 #=> TrueTrue is 1 #=> FalseFalse == 0 #=> TrueFalse is 0 #=> FalseNone == 0 #=> FalseNone is 0 #=> False

• Trueは1と同値かつ非同一、Falseは0と同値かつ非同一

list1 = []list2 = []list1 == list2 #=> Truelist1 is list2 #=> Falselist2 = list1list1 is list2 #=> True

• '==' は同値判定、'is' は同一判定(反対は 'is not')

34

Page 35: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

比較演算子PHP Python

1 > 01 >= 10 < 11 <= 1

0 < $x && $x < 3

1 > 01 >= 10 < 11 <= 1

0 < x < 30 < 1 <= 2 == 2 < 3

•複数の比較は && で連結 •複数の比較を連結できる

35

Page 36: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

論理演算子PHP Python

! x x && y x and yx || y x or y x xor y

$x = $val or die(); # ($x = $val) or die() と同じ

not xx and yx or y# --

x = val or die() # x = (val or die()) と同じ

•優先度が違う2種類を用意 • '!', '&&', '||' は使えない

36

Page 37: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

論理演算子の値PHP Python

10 && 0 #=> FALSE0 || 10 #=> TRUE

$x = $y = "";$v = $x ?: $y ?: "default";

10 and 0 #=> 00 or 10 #=> 10

x = y = ""v = x or y or "default"

•論理演算子の結果は必ずTRUEかFALSE

•論理演算子の結果がTrueやFalseにならない

37

Page 38: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

メンバシップPHP Python

# 該当演算子なし 2 in [1, 2, 3] # True4 not in [1, 2, 3] # True"a" in {"a": 10} # True"b" not in {"a": 10} # True"ana" in "banana" # True

• listやtupleやsetの場合は要素が含まれるか?

• dictならキーに含むか?•文字列なら部分文字列か?

38

Page 39: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

算術演算子PHP Python

1 + 11 - 11 * 110 / 3 #=> 3.3333333310 % 3 #=> 1pow(2, 10) #=> 1024

1 + 11 - 11 * 110 / 3 #=> 310 % 3 #=> 12**10 #=> 1024

39

Page 40: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

結合演算子PHP Python

"foo" . "bar" #=> "foobar" "foo" + "bar" # stru"foo" + u"bar" # unicodeu"foo" + "bar" # unicode"foo" + u"bar" # unicode

•ひとつでもunicodeなら結果もunicode

•すべてstrのときだけ結果もstr

40

Page 41: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

代入演算子PHP Python

$x = 1$x += 1$x -= 1$x *= 1$x /= 1$x %= 1$x .= "str"

x = 1x += 1x -= 1x *= 1x /= 1x %= 1x += "str"

41

Page 42: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

ビット演算子、シフト演算子PHP Python

$x & 0xFF$x | 0xFF$x ^ 0xFF~ $x

$x << 2$x >> 2

x & 0xFFx | 0xFFx ^ 0xFF~ x

x << 2x >> 2

42

Page 43: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

三項演算子(条件演算子)PHP Python

$v = $x > 0 ? $x : - $x;

$v = $x > 0 ? $x : ($y > 0 ? $y : ($z > 0 ? $z : -9999));

v = (x if x > 0 else - x)

v = (x if x > 0 else \ y if y > 0 else \ z if z > 0 else -9999)

• Perlの後置記法と間違えないよう、カッコ推奨

•つなげること自体にはカッコいらず

•演算子優先順位の問題により、つなげるときはカッコが必要

43

Page 44: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

その他✤ 演算子オーバーロードが可能✤ x++(インクリメント)や x--(デクリメント)は、ない✤ `shell command` は、ない(import os; os.system("shell command") を使う)

44

Page 45: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

コンテナ

【関連ドキュメント】

• チュートリアル: 5. データ構造http://www.python.jp/doc/release/tut/node7.html

• ライブラリリファレンス: 3.6.4 変更可能なシーケンス型http://www.python.jp/doc/release/lib/typesseq-mutable.html

• ライブラリリファレンス: 3.8 マップ型http://www.python.jp/doc/release/lib/typesmapping.html

45

Page 46: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

リスト (List)PHP Python

# 配列$arr = array(10, 20, 30,);echo $arr[2];$arr[] = 40;var_export($arr);

# リスト(更新可能)list1 = [10, 20, 30,]print list1[2]list1.append(40)print repr(list1)

•実体は連想配列•最後の ',' は省略可能

•連結リストではない•最後の ',' は省略可能

46

Page 47: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

リスト: 代入によるコピーPHP Python

$arr1 = array(10, 20, 30);$arr2 = $arr1;

$arr2[1] = 25;var_export($arr1); #=> array(0=>10, # 1=>20, # 2=>30) # (変更されてない)

list1 = [10, 20, 30]list2 = list1

list2[1] = 25print repr(list1) #=> [10, 25, 30] # (変更された!)

配列がコピーされる 同じリストを共有

•コピーは list2 = list1[:](スライスについては後述)

47

Page 48: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

リスト: 繰り返しPHP Python

## 単純ループforeach ($arr as $x) echo $x;## カウンタ付きループforeach ($arr as $i=>$x) echo $i, $x;

## 単純ループfor x in list1: print x## カウンタ付きループfor i, x in enumerate(list1): print i, x

48

Page 49: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

リスト: 各種操作Python

## リストの長さlist1 = ['a', 'b', 'c']print len(list1) #=> 3

## 要素が含まれるかどうかprint 'b' in list1 #=> Trueprint 'x' in list1 #=> False

## 要素の連結print "".join(list1) # 'abc'print ",".join(list1) # 'a,b,c'

### 逆順にする (破壊的)list1.reverse()print list1 #=> ['c','b','a']

49

Page 50: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

リスト: 各種操作Python

## 要素を追加する (破壊的)list1 = []list1.append(10)list1.append(20)print list1 #=> [10, 20]

## 他のリストを追加 (破壊的)list1.extend([30, 40])print list1 #=> [10, 20, 30, 40]

## 添字を指定して追加 (破壊的)list1.insert(3, 'A')print list1 #=> [10, 20, 30, 'A', 40]

50

Page 51: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

リスト: 各種操作Python

## 一致する要素の添字を返すlist1 = ['a','b','c','b']print list1.index('b') #=> 1print list1.index('x') #=> ValueError

## 一致する要素の数を返すprint list1.count('b') #=> 2

51

Page 52: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

リスト: 各種操作Python

## 一致する最初の要素を取り除く (破壊的)list1 = [3, 1, 4, 1, 5, 9]list1.remove(1)print list1 #=> [3,4,1,5,9]list1.remove(999) #=> ValueError

## 最後の要素を取り除いて返す (破壊的)print list1.pop() #=> 9print list1 #=> [3,4,1,5][].pop() #=> IndexError

52

Page 53: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

リスト: 各種操作Python

## ソート (破壊的)list1 = [3, 1, 4, 1, 5, 9]list1.sort()print list1 #=> [1, 1, 3, 4, 5, 9]

## ソート (非破壊的)list1 = [3, 1, 4, 1, 5, 9]list2 = sorted(list1)print list2 #=> [1, 1, 3, 4, 5, 9]print list1 #=> [3, 1, 4, 1, 5, 9]

## 逆順ソート (破壊的)list1.sort(reverse=True)print list1 #=> [9, 5, 4, 3, 1, 1]

## 要素を指定したソート (破壊的)list2 = [['A',3], ['B',1], ['C',2]]list2.sort(key=lambda x: x[1])print list2 #=> [['B', 1], ['C', 2], ['A', 3]]

53

Page 54: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

タプル (Tuple)

✤ タプル (tuple)✤ 変更できないリスト✤ リストより軽量✤ 辞書のキーに指定可能✤ リストと同じ操作が可能(非破壊操作のみ)

Python

# タプル(更新不可)tuple1 = (10, 20, 30)print tuple1[2]tuple1[2] = 31 #=> TypeErrorprint repr(tuple1)

var = (9) # 整数値var = (9, ) # タプルvar = () # 空タプル

54

Page 55: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

辞書 (Dictionary)PHP Python

# 連想配列$arr = array("a"=>1, "b"=>2);

echo $arr["b"]; #=> 2$arr["c"] = 3;

var_export($arr); #=> array('a'=>1,'b'=>2,'c'=>3)

# 辞書dict1 = {"a":1, "b":2 } # or dict1 = dict(a=1, b=2)print dict1["b"] #=> 2dict1["c"] = 3

print dict1 # or repr(dict1) #=> {'a': 1, 'c': 3, 'b': 2}

•順番が保存される •順番は保存されない

55

Page 56: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

辞書: キーが存在しないときPHP Python

$arr = array('A'=>1, 'B'=>2);echo $arr['A'];echo $arr['X']; #=> NULL

echo isset($arr['X']) ? $arr['X'] : 10;

dict1 = {'A':1, 'B':2}print dict1['A']print dict1['X'] #=> KeyError

print dict1.get('X', 10) #=> 10print dict1.get('X') #=> None

•キーが存在しないときはKeyErrorが発生

• dict.get()でキーがないときのデフォルト値を指定可能

•キーが存在しないときはNULL (Warningも出る)

•キーがないときのデフォルト値を指定する方法なし

56

Page 57: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

辞書: 繰り返しPHP Python

foreach ($arr as $key=>$val) echo $key, $val;

foreach ($arr as $item) echo $item; # 値

for key, val in dict1.iteritems(): print key, val

for item in dict1: print item # キー

• dict.iteritems()を使う•使わない場合はキーの繰り返し (dict.iterkeys()推奨)

•「as $key=>$val」ならキーと値の繰り返し

•「as $val」なら値の繰返し

57

Page 58: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

辞書: 各種操作Python

## 要素の数dict1 = {'A':1, 'B':2}print len(dict1) #=> 2

## すべてのキーを取り出すprint dict1.keys() #=>['A','B']

## すべての値を取り出すprint dict1.values() #=> [1,2]

## キーが存在するかどうかprint dict1.has_key('A')print 'A' in dict1

## 要素を削除 (破壊的)del dict1['A']print dict1 #=> {'B':2}del dict1['C'] #=> KeyError

58

Page 59: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

辞書: 各種操作Python

## コピーdict1 = {'A': 1, 'B': 2}dict2 = dict1.copy()print dict2 #=> {'A': 1, 'B': 2}

## 別の辞書で更新 (破壊的)dict2.update({'C':3})print dict2 #=> {'A': 1, 'C': 3, 'B': 2}

## キーを指定して削除 (破壊的)print dict2.pop('C') #=> 3print dict2.pop('C') #=> KeyErrorprint dict2.pop('C', 3) #=> 3

## すべてを削除 (破壊的)dict2.clear()print dict2 #=> {}

59

Page 60: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

辞書: 各種操作Python

## キーがないときだけ値を追加dict1 = {'A':1, 'B':2}dict1.setdefault('C', 3) # 'C' はないので追加され、かつ 3 が返されるdict1.setdefault('C', 9) # 'C' はあるので追加されず、かつ # dict['C'] が返される## 使い道:たとえばこれがif 'key' not in dict1: dict1['key'] = []dict1['key'].append('val')## こう書けるdict1.setdefault('key', []).append('val')

60

Page 61: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

集合 (Set)

✤ set ✤ 値の集まり✤ 順序を持たない✤ 値の重複を許さない✤ 変更可能✤ 辞書のキーに指定可能な値のみ受け付ける

✤ frozenset ✤ 変更不可なset✤ 辞書のキーに指定可能

Python

# 集合 (set)set1 = set(['a', 'b'])print set1 #=> set(['a', 'b']) # 順序を持たないset1.add('c')print set1 #=> set(['a', 'c', 'b'])# 値の重複を許さない set1.add('a')print set1 #=> set(['a', 'c', 'b'])

リストや辞書は不可

61

Page 62: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

集合: よくある例Python

## リストを使った判定(遅い)members = ['Haruhi', 'Mikuru', 'Yuki', 'Itsuki', 'Kyon']for i in xrange(10000): found = 'Tsuruya' in members

## 集合を使った判定(速い)members = set(['Haruhi', 'Mikuru', 'Yuki', 'Itsuki', 'Kyon'])for i in xrange(10000): found = 'Tsuruya' in members

62

Page 63: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

集合: 各種操作Python

## 値を追加set1 = set(['a', 'b', 'c'])set1.add('d')

## 値を削除set1.remove('d')set1.remove('d') #=> KeyErrorset1.discard('d') # 値がなくても # 例外を投げない## 要素数print len(set1) #=> 3

## 値があるかどうか'a' in set1 #=> True'A' not in set2 #=> True

## 繰り返しfor x in set1: print x, #=> a c b

## 浅いコピーset2 = set1.copy()

63

Page 64: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

集合: 各種演算Python

set1 = set(['a', 'b'])set2 = set(['b', 'c'])## 和集合 (∪)set1 | set2 #=> set(['a','b','c'])## 積集合 (∩)set1 & set2 #=> set(['b'])## 差集合 (∪)set1 - set2 #=> set(['a'])## 対象差 (△)set1 ^ set2 #=> set(['a','c'])

## 包含関係 (⊆、⊇)set3 = set(['a', 'b', 'c'])set4 = set(['b', 'c'])set3 > set4 #=> Trueset3 < set4 #=> Falseset3 >= set4 #=> Trueset3 <= set4 #=> Falseset3 > set3 #=> Falseset3 < set3 #=> Falseset3 >= set3 #=> Trueset3 <= set3 #=> True

64

Page 65: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

シーケンス、スライス

【関連ドキュメント】

• ライブラリリファレンス: 3.6 シーケンス型 str, unicode, list, tuple, buffer, xrangehttp://www.python.jp/doc/release/lib/typesseq.html

• 言語仕様リファレンス: 3 スライス表記 (slicing)http://www.python.jp/doc/release/ref/slicings.html

65

Page 66: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

シーケンスとは?✤ (主に) リスト、タプル、文字列のこと✤ どれも同じような操作を提供

Python

L = ['a', 'b', 'c', ] # リストT = ('a', 'b', 'c', ) # タプルS = "abc" # 文字列

# 要素へのアクセスprint L[2], T[2], S[2] #=> c c c

# 要素の繰り返しfor x in L: print x, #=> a b cfor x in T: print x, #=> a b cfor x in S: print x, #=> a b c

66

Page 67: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

シーケンス: 操作Python

# 要素があるかどうかprint 'b' in Lprint 'b' in Tprint 'b' in S

# 要素が含まれないかprint 'x' not in Lprint 'x' not in Tprint 'x' not in S

# 結合print L + ['d'] #=> ['a','b','c','d']print T + ('d',) #=> ('a','b','c','d')print S + "d" #=> 'abcd'

# 長さprint len(L) #=> 3print len(T) #=> 3print len(S) #=> 3

67

Page 68: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

シーケンス: 変換Python

# リストへ変換print list(T) #=> ['a', 'b', 'c']print list(S) #=> ['a', 'b', 'c']

# タプルへ変換print tuple(L) #=> ('a', 'b', 'c')print tuple(S) #=> ('a', 'b', 'c')

# 文字列へ変換print str(L) #=> "['a', 'b', 'c']"print str(T) #=> "('a', 'b', 'c')"

# 要素を連結print "".join(L) #=> 'abc'print "".join(T) #=> 'abc'

68

Page 69: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

スライス: 部分要素の取り出しPython

# -5 -4 -3 -2 -1# 0 1 2 3 4L = ['a','b','c','d','e'] # リストT = ('a','b','c','d','e') # タプルS = "abcde" # 文字列

# 部分要素の取り出しprint L[1:3] #=> ['b', 'c']print T[1:3] #=> ('b', 'c')print S[1:3] #=> 'bc'print L[1:-1] #=> ['b', 'c', 'd']print T[1:-1] #=> ('b', 'c', 'd')print S[1:-1] #=> 'bcd'• L[1:3] なら L[1] と L[2] は含

まれるが L[3] は含まれないことに注意

• L[n:m] の長さは m-n•マイナスは後ろから数える

69

Page 70: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

スライス: 部分要素の変更Python

# 部分要素の変更L = ['a', 'b', 'c', 'd', 'e']print L[1:3] #=> ['b', 'c']L[1:3] = ('X', 'Y', 'Z')print L #=> ['a', 'X', 'Y', 'Z', 'd', 'e']

型や要素数が異なっていてもよい

•タプルと文字列は変更不可 (immutable) なので、TypeError になる

70

Page 71: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

スライス: 添字省略時Python

# 0 1 2 3 4L = ['a', 'b', 'c', 'd', 'e']print L[:2] #=> ['a', 'b']print L[2:] #=> ['c', 'd', 'e']print L[:] #=> ['a','b','c','d','e']

•最初の添字を省略すると 0•最後の添字を省略すると len(L)

L == L[:n] + L[n:] # 常に真

L2 = L[:] # 全体のコピー

L3 = L # 同じリストを共有

71

Page 72: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

文字列操作

【関連ドキュメント】

• ライブラリリファレンス: 3.6.1 文字列メソッドhttp://www.python.jp/doc/release/lib/string-methods.html

• チュートリアル: 3.1.2 文字列http://www.python.jp/doc/release/tut/node5.html#SECTION005120000000000000000

72

Page 73: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

文字列操作Python

# 単純結合'Ha'+'ru'+'hi' #=> 'Haruhi'

# 複数文字列結合''.join(['s', 'o', 's']) #=> 'sos''/'.join(['s','o','s']) #=> 's/o/s'

# 繰り返し'Wa' * 3 #=> 'WaWaWa'

# 部分文字列"Haruhi"[2:5] #=> 'ruh'

# 長さlen("Suzumiya") #=> 8

# 数値に変換int("10") #=> 10int("FF", 16) #=> 255 (16進数)float("3.14") #=> 3.1400000001

73

Page 74: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

文字列操作Python

# 書式 (printf相当)x, y = 'A', 123'x=%s, y=%s' % (x, y) # x=A, y=123'<%5s>' % x # < A>'<%-5s>' % x # <A >'<%5d>' % y # < 123>'<%-5d>' % y # <123 >'<%05d>' % y # <00123>

'pi=%f' % 3.1415 # pi=3.141500'pi=%7.3f' % 3.1415 # pi= 3.142'list=%r' % [10,20,30] # list=[10, 20, 30]'dict=%r' % {'a':10} # dict={'a': 10}'a=%(a)s, b=%(b)s' % {'a':10,'b':20} # x=10, y=20'x=%(x)s, y=%(y)s' % locals() # x=A, y=123

値が複数ならタプルで指定

74

Page 75: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

文字列操作Python

# 部分文字列を検索"Haruhi".find("uh") #=> 3"Haruhi".find("x") #=> -1"Haruhi".index("uh") #=> 3"Haruhi".index("x") #=> ValueError

# 逆から検索"Mikuru".rfind("u") #=> 3"Mikuru".rindex("u") #=> 5

# 開始文字列をチェック'Nyoroon'.startswith('Nyo') #=> True# 終了文字列をチェック'Dounyoro'.endswith('nyoro') #=> True

75

Page 76: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

文字列操作Python

# 置換"Mikuru".replace('ku', 'chi') #=> 'Michiru'# カウント'kamadouma'.count('ma') #=> 2# 空白文字の削除" Kyon ".strip() #=> 'Kyon'" Kyon ".lstrip() #=> 'Kyon '" Kyon ".rstrip() #=> ' Kyon'

# 行に分割s = """HaruhiMikuruYuki"""s.splitlines() #=> ['Haruhi', 'Mikuru', 'Yuki']s.splitlines(True) #=> ['Haruhi\n', 'Mikuru\n', 'Yuki\n']

76

Page 77: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

文字列操作Python

# 大文字に変換"yuki".upper() #=> "YUKI"

# 小文字に変換"YUKI".lower() #=> "yuki"

# 大文字・小文字を入れ替える"Yuki".swapcase() #=> 'yUKI'

# 文字種類の判別"Endless8".isalnum() #=> True"Endless8".isalpha() #=> False"8".isdigit() #=> True"endless8".islower() #=> True"ENDLESS8".isupper() #=> True" ".isspace() #=> True"End Less Eight".istitle() #=> True

77

Page 78: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

文字列操作Python

# キャピタライズ'yuki'.capitalize() #=> Yuki

# 単語ごとにキャピタライズ"haruhi mikuru YUKI".title() #=> 'Haruhi Mikuru Yuki'

# 中央揃え'Kyon'.center(10) #=> ' Kyon ' (長さ10)

# 文字列幅の調整"Yuki".ljust(8, '!') #=> 'Yuki!!!!'"Yuki".rjust(8, '!') #=> '!!!!Yuki'

# 頭にゼロを追加'8'.zfill(3) #=> '008'

# タブを半角空白に展開"Nyo\troon".expandtabs(8) #=> 'Nyo roon'

78

Page 79: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

基本構文

【関連ドキュメント】

• チュートリアル: 4. その他の制御フローツールhttp://www.python.jp/doc/release/tut/node6.html

• 言語仕様リファレンス: 6. 単純文 (simple statement)http://www.python.jp/doc/release/ref/simple.html

• 言語仕様リファレンス: 7. 複合文 (compound statement)http://www.python.jp/doc/release/ref/compound.html

79

Page 80: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

print文PHP Python

$x = 10; $y = 20;echo 'x=', $x, ', y=', $y, "\n";echo "x=$x, y=$y\n";

x = 10; y = 20print 'x=', x, ', y=', yprint 'x=%s, y=%s' % (x, y)

•改行は"\n"で明示•引数間に空白は入らない

•自動的に改行される("," で終わると改行しない)

•引数間に半角空白が入る

80

Page 81: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

代入文PHP Python

$x = 0;

$x += 1;

$x++;

# 多重代入list($x, $y) = array(10, 20);list($x, $y) = array($y, $x);

x = 0

x += 1

# インクリメントはなし

# 多重代入x, y = 10, 20 # or (10,20)x, y = y, x # or (y, x)

81

Page 82: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

if文PHP Python

$x = 0;if ($x > 0) { echo "$x is positivie.\n";} elseif ($x < 0) { echo "$x is negative.\n";} else { echo "$x is zero.\n";}

x = 0if x > 0: print "%s is positive." % xelif x < 0: print "%s is negative." % xelse: print "%s is zero." % x

82

Page 83: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

while文PHP Python

$i = 0;while (++$i <= 10) { echo $i, "\n";}

i = 1while i <= 10: print i i += 1

• do { } while () も利用可能

• do - while は、なし

83

Page 84: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

for文PHP Python

$arr = array(10, 20, 30);foreach ($arr as $item) { echo $item, "\n";}

for ($i=0; $i<10; $i++) { echo $i, "\n";}

list1 = [10, 20, 30]for item in list1: print item

for i in xrange(1, 10): print i

• for (;;) はないので、xrange()で代用 (後述)• for (;;) も利用可能

84

Page 85: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

break文、continue文PHP Python

foreach ($arr as $item) { if ($item === NULL) continue; if ($item === 100) { echo "found!\n"; break; }}

for item in list1: if item is None: continue if item == 10: print "found!" break

85

Page 86: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

pass文PHP Python

if (! $name) { // TODO: エラー処理

} else { echo $name;}

if not name: ## TODO: エラー処理 passelse: print name

•何もしないことを表すためにpass文が必要

86

Page 87: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

del文PHP Python

$x = 1;echo $x; #=> 1unset($x);echo $x; # Notice: undefined variable$arr = array("a"=>123);echo $arr["a"]; #=> 123unset($arr["a"]);echo $arr["a"] # Notice: Undefined index

x = 1print x #=> 1del xprint x # NameError

dict1 = {"a":123}print dict1["a"] #=> 123del dict1["a"]print dict1["a"] # KeyError

87

Page 88: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

else節PHP Python

$arr = array(1, 2, 3);$found = FALSE;foreach ($arr as $item) { if ($item == 100) { $found = TRUE; break; }}if (! $found) echo "not found\n";

list1 = [1, 2, 3]for item in list1: if item == 100: breakelse: print "not found"

• forとwhileにelse節を追加できる

• breakしなかったときだけelse節を実行

88

Page 89: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

try文PHP Python

try { throw new Exception("msg");} catch (Exception $ex) { echo $ex->message();} catch (OtherException $ex) { throw $ex;}

try: raise Exception("msg")except Exception, ex: print ex.messageexcept OtherException, ex: raisefinally: print "finally"

• finally節が利用可能

89

Page 90: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

assert文PHP Python

$var = NULL;assert('$var != NULL');

var = Noneassert var != None# これは次と同等if __debug__: if not (var != None): raise AssertionError

• assert 文の引数は、式そのもの

• Python起動時に -O を指定すると無視される

• assert関数の引数は、式を表す文字列

• assert_option() で挙動を指定できる

90

Page 91: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

with文Python

from __future__ \ import with_statementwith open('file.txt') as f: for line in f: print line,## with文が終了した時点で## fが自動的にクローズされる

## これは次と(だいたい) 同じf = open('file.txt')f.__enter__()try: for line in f: pirnt line,finally: f.__exit__()

内部でf.close()を実行•参照: PEP 0343 The "with" statementhttp://www.python.org/peps/pep-0343.html

Python2.5では必要

91

Page 92: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

内包表記 (list complehension)Python

list1 = [1, 2, 3, ]list2 = [ i*i for i in list1 ]print list2 #=> [1, 4, 9]

## これは次と同等list2 = []for i in list1: list2.append(i*i)

list2 = [ i*i for i in list1 if i % 2 == 1 ]print list2 #=> [1, 9]

## これは次と同等list2 = []for i in list1: if i % 2 == 1: list2.append(i*i)

• for文より簡潔で高速でわかりやすい• for文は動作の記述、内包表記は意図の記述

92

Page 93: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

関数

【関連ドキュメント】

• チュートリアル: 4.7 関数定義についてもう少しhttp://www.python.jp/doc/release/tut/node6.html#SECTION006700000000000000000

• ライブラリリファレンス:2.1 組み込み関数http://www.python.jp/doc/release/lib/built-in-funcs.html

• 言語仕様リファレンス: 7.6 関数定義http://www.python.jp/doc/release/ref/function.html

93

Page 94: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

関数定義PHP Python

/** フィボナッチ数を計算 */function fib($n) { if ($n <= 2) { return 1; } else { return fib($n-1)+fib($n-2); }}

echo fib(30);

def fib(n): """フィボナッチ数を計算""" if n <= 2: return 1 else: return fib(n-1)+fib(n-2)

print fib(30)help(fib)

ドキュメントを表示

関数定義の冒頭に記述(構文としてサポート)

94

Page 95: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

引数のコピーPHP Python

function f($arr) { $arr[0] = 123; var_export($arr);}$arr = array(10);f($arr); #=> array(0=>123,)var_export($arr); #=> array(0=>10, )

def f(list1): list1[0] = 123 print repr(list1)

list1 = [10]f(list1) #=> [123]print repr(list1) #=> [123]

•引数の配列はコピーされる•引数のリストや辞書はコピーされない

95

Page 96: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

デフォルト引数PHP Python

function f($x, $y=0, $z=0) { echo $x, $y, $z;}

function g($a=array()) { $a[] = 1; var_export($a);}g(); g(); g();

def f(x, y=0, z=0): print x, y, z

def g(a=[]): a.append(1) print repr(a)

g(); g(); g()

同じリストが毎回使われる新しい配列が

毎回作成される

96

Page 97: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

キーワード引数PHP Python

## 該当機能なし ## 仮引数の名前を使って## 実引数を指定するdef f(x, y=0, z=0): return x + y + z

## どれも f(5, 0, 10) と同じprint f(5, z=10)print f(z=10, x=5)

97

Page 98: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

可変長引数PHP Python

function f() { $args = func_get_args(); var_export($args);}f(10, "A", TRUE);## 実行結果array (0 => 10, 1 => 'A', 2 => true,)

def f(*args, **kwargs): print repr(args) # タプル print repr(kwargs) # 辞書

f(10, "A", True, x=30, y=40)## 実行結果(10, 'A', True){'y': 40, 'x': 30}

98

Page 99: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

可変長引数:サンプルPython

def img(src, **attrs): html = '<img src="%s" ' % src for k, v in attrs.iteritems(): html += ' %s="%s" ' % (k, v) html += ' />' return html

print img('logo.gif', id='logo_gif', alt='logo image') #=> <img src="logo.gif" alt="logo image" id="logo_gif" />

普通の引数と可変長引数とが混在可能

99

Page 100: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

関数オブジェクトPHP Python

## 該当機能なし def f(a, b): return a+b;g = f # 関数を代入print g(2, 3) #=> 5print dir(g) # 属性を表示 print g.func_name #=> f

•「関数を定義する」=「関数オブジェクトを作成し変数に代入する」

•関数もデータである

100

Page 101: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

無名関数PHP Python

## その場で関数を作成$f = create_function( '$a, $b', 'return $a+$b;' );

echo $f(10, 20); #=> 30var_export($f); #=> 'lambda_1'

## その場で関数を作成f = lambda a, b: a + b## これは次とほぼ同じ## def f(a, b): return a+b

print f(10, 20) #=> 30print f.func_name #=> '<lambda>'

•本体は式のみ(文は不可)•本体を文字列で指定(< PHP5.3)

101

Page 102: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

関数の再定義PHP Python

function f(x){ return x+x;}function f(x) { #=> Fatal Error return 2*x;}

def f(x): return x+x

def f(x): return 2*x

•関数の再定義は、「変数への再代入」でしかない

•同名の関数を再定義できない

102

Page 103: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

関数オブジェクト:サンプルPHP Python

function sigma($x, $y, $f) { $sum = 0; for ($i=$x; $i<=$y; $i++) $sum += $f($i); return $sum;}function pow2($n) { return $n*$n;}sigma(1, 10, "pow2");

def sigma(x, y, f): sum = 0 for i in xrange(x, y+1): sum += f(i) return sum

def pow2(n): return n*n

sigma(1, 10, pow2)文字列で指定

関数オブジェクトを指定

103

Page 104: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

変数のスコープPHP Python

list($x, $y, $z)=array(1,2,3);function f() { $x = 7; # local var global $y; $y = 9; # global var echo $z; # undefined var}f()echo "$x $y $z\n"; #=>1 9 3

x, y, z = 1, 2, 3 # globaldef f(): x = 7 # local var global y y = 9 # global var print z # global var

f()print x, y, z #=> 1 9 3

•参照は何もしなくても可•代入はglobal宣言が必要

•参照にも代入にもglobal宣言が必要

104

Page 105: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

関数内関数PHP Python

function g($x, $y) { return ($x+$y)*($x-$y);}function f($a, $b, $c, $d) { return g($a, $b) + g($c, $d);}## (2+3)*(2-3) + (4+5)*(4-5)print f(2, 3, 4, 5)

def f(a, b, c, d): def g(x, y): return (x+y)*(x-y) return g(a, b) + g(c, d) ## (2+3)*(2-3) + (4+5)*(4-5)print f(2, 3, 4, 5)

• g() はグローバル(誰でもアクセス可)

• g() はローカル(f() の外からは見えない)

105

Page 106: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

組み込み関数Python

len(seq) # 長さを求めるrepr(val) # val の文字列表現を返すrange(start, end, step) # startからend-1までのリストを返すxrange(start, end, step) # range() のイテレータ版sorted(seq) # ソートした新しいseqを返すsum(seq) # seqに含まれる数値を合計するvars(obj) # obj.__dict__ と同じiter(obj) # obj.__iter__() と同じ

106

Page 107: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

組み込み関数 (cont)Python

id(obj) # オブジェクトIDを返すglobals() # グローバル変数を表す辞書を返すlocals() # ローカル変数を表す辞書を返す dir(obj) # 属性名の一覧 getattr(obj, name) # 属性値を取り出すsetattr(obj, name, val) # 属性値を設定するdelattr(obj, name) # 属性を削除する

•詳しい一覧は http://www.python.jp/doc/release/lib/built-in-funcs.html

107

Page 108: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

モジュール、パッケージ

【関連ドキュメント】

• チュートリアル: 6. モジュールhttp://www.python.jp/doc/release/tut/node8.html

• 言語仕様リファレンス: 6.12 import 文http://www.python.jp/doc/release/ref/import.html

108

Page 109: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

モジュールとは?✤ ライブラリファイルのこと✤ 実体はただのPythonスクリプト

util.py

PI = 3.14def add(x, y): return x+ydef sub(x, y): return x-ydef _debug(s): return "*** "+repr(s);

109

Page 110: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

importmain.py

import utilprint util #=> <module 'util' from 'util.pyc'>print util.PI #=> 3.14print util.add(10, 20) #=> 30print util.sub(10, 20) #=> -10print util._debug(123) #=> *** 123

•パッケージ名を接頭辞につけてアクセスする必要がある

•実際には、変数utilにモジュールオブジェクトが代入されるだけ

110

Page 111: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

frommain.py

from util import PI, addprint PI #=> 3.14print add(10, 20) #=> 30print sub(10, 20) #=> NameError: name 'sub' is not defindprint util.sub(10, 20) #=> NameError: name 'util' is not defined

from util import *print sub(10, 20) #=> -10print _debug(123) #=> NameError: name '_debug' is not defined

必要なものだけimport可能

すべてをimportする、ただし '_' 始まりは除く

• PI = util.PI と同等•変数 util は定義されない

111

Page 112: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

注意main.py

import util # OKfrom util import add # OKimport util.add # ImportError

• from がないときは、import の引数はモジュール名でなくてはいけない (関数名などは指定できない)

112

Page 113: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

__all__util.py main.py

__all__ = ('PI', 'add')PI = 3.14def add(x, y): return x+ydef sub(x, y): return x-y

from util import *print PIprint add(10, 20)print sub(10, 20) #=> NameErrorfrom util import subprint sub(10, 20) #=> -10

•「import *」したときに読み込まれる変数や関数の名前を列挙する

• __all__ に列挙されてなくても、明示的にimportすることが可能

113

Page 114: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

asmain.py

import util as utilityprint utility.add(10, 20)from util import add as plus, sub as minusprint plus(10, 20)

try: import cStringIO as StringIO # C実装版があればそれを使うexcept ImportError: import StringIO # なければ pure Python 版を使う

名前を変えてimport可能

• StringIO = cStringIO と同等

114

Page 115: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

__name__util.py

print __name__ #=> util (または main )

def add(x, y): return x+y

if __name__ == '__main__': assert add(10, 20) == 30

自分のパッケージ名を表す特殊変数

•他からimportされたときは "util" に•そうでなければ "__main__" に

コマンドラインでutil.pyが指定されたときだけ実行

115

Page 116: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

変数のスコープfoo.py main.py

X = 10 # モジュールローカルdef set_x(x) global X X = x

import foofrom foo import Xprint X # モジュールローカルX = 20print X, foo.X #=> 20 10

foo.set_x(30)print X, foo.X #=> 20 30

• Pythonの「global」はモジュールローカル

これは X = foo.X 相当

foo.X は変更されない

X は変更されない

116

Page 117: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

__builtin__パッケージpython python

import __builtin__## 組み込みの関数や## クラスの一覧print dir(__builtin__)## またはfor k in dir(__builtin__): v = getattr(__builtin__, k) print v

def h(s): s = s.replace('&', '&amp;') s = s.replace('<', '&lt;') s = s.replace('>', '&gt;') return s

__builtin__.h = h

• __builtin__は組み込み関数などが入っているパッケージ

• PHPでいう「グローバル」は、Pythonでは「組み込み」(= __builtin__ に登録した)

可能だが非推奨!!

117

Page 118: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

パッケージとは?✤ 複数のモジュールを集めたディレクトリ✤ __init__.py が必要

(中身は空でよい)✤ ディレクトリは入れ子可能

mypkg/__init__.py

mypkg/mod1.py

## 中身は空でよい

def add(x, y): return x+y

mypkg/mod2.py

def sub(x, y): return x-y

118

Page 119: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

パッケージのimportmain.py

import mypkgprint mypkg #=> <module 'mypkg' from 'mypkg/__init__.py'>print mypkg.mod1 #=> AttributeError: 'module' object has no attribute 'mod1'

パッケージをimportするとmypkg/__init__ モジュールがimportされる

サブモジュールが自動的にimportされるわけではない

119

Page 120: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

サブモジュールの importmain.py

import mypkg.mod1

print mypkg #=> <module 'mypkg' from 'mypkg/__init__.pyc'>

print mypkg.mod1 #=> <module 'mypkg.mod1' from 'mypkg/mod1.pyc'>

print mod1 #=> NameError: name 'mod1' is not defined

サブモジュールは '.' で区切る

親モジュールがインポートされる

サブモジュールがインポートされる

パッケージ名が必要

120

Page 121: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

サブモジュールの from importmain.py

from mypkg import mod1, mod2print mod1 #=> <module 'mypkg.mod1' from 'mypkg/mod1.pyc'>

from mypkg import mod1 as m1, mod2 as m2print m1 #=> <module 'mypkg.mod1' from 'mypkg/mod1.pyc'>

パッケージ名なしでアクセス可能(mod1 = mypkg.mod1 と同等)

別名でimport可能

121

Page 122: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

サブモジュールの import *mypkg/__init__.py

import mod1, mod2__all__ = ('mod1', )

main.py

from mypkg import *print mod1 #=> <module 'mypkg.mod1'>print mod2 #=> NameError

import mypkgprint mypkg.mod1 #=> <module 'mypkg.mod1'>print mypkg.mod2 #=> <module 'mypkg.mod1'>

122

Page 123: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

標準添付モジュール✤ sys … システムまわり✤ os … OSやファイルシステム✤ os.path … ファイルパス✤ time … 時刻関連✤ re … 正規表現✤ __builtin__ … 組込の関数やクラスが定義されている

参考: ライブラリインデックスhttp://www.python.jp/doc/release/lib/lib.html

123

Page 124: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

その他✤ 検索パスはリスト sys.path に格納されている

✤ 環境変数 $PYTHONPATH を設定すると、sys.path に追加される

import syssys.path.append("lib") # 末尾に追加sys.path.insert(0, "lib") # 先頭に追加

124

Page 125: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

オブジェクト指向

【関連ドキュメント】

• チュートリアル: 9. クラスhttp://www.python.jp/doc/release/tut/node11.html

• 言語仕様リファレンス: 7.7 クラス定義http://www.python.jp/doc/release/ref/class.html

125

Page 126: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

クラスとコンストラクタPHP Python

class User { var $name; function __construct($name) { $this->name = $name; }}

class User(object): def __init__(self, name): self.name = name

•親クラスとして object を必ず指定すること!

•コンストラクタは__init__()、第1引数はselfを指定すること!

•コンストラクタは__construct() 

•インスタンスを表す疑似変数は$this

126

Page 127: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

インスタンスオブジェクトPHP Python

$u = new User("Haruhi");echo $u->name;$u->name = "Suzumiya";$u->age = 16; # OKvar_export($u);

u = User("Haruhi")print u.nameu.name = "Suzumiya"u.age = 16 # OKprint u.__dict__ # or vars(u)

•クラスを関数のように呼び出して生成

•未定義のインスタンス変数に代入可能

• new演算子で生成•未定義のインスタンス変数に代入可能

127

Page 128: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

インスタンスメソッドPHP Python

class User { var $name; function hello() { echo "Hello $this->name!"; }}$u = new User();$u->name = "Haruhi";$u->hello(); #=> Hello Haruhi!

class User(object): def hello(self): print "Hello %s!" % self.name

u = User()u.name = "Haruhi"u.hello() #=> Hello Haruhi!

•予約語 def で定義•第1引数は必ずselfを指定•予約語 function で定義

128

Page 129: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

継承PHP Python

class Animal { function __construct($name) { $this->name = $name; }}class Dog extends Animal { function __construct($name) { parent::__construct($name); }}

class Animal(object): def __init__(self, name): self.name = name

class Dog(Animal): def __init__(self, name): Animal.__init__(self, name)

•親クラスのコンストラクタを呼び出す (必要なら)

•親クラスのコンストラクタを呼び出す (必要なら)

129

Page 130: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

superPHP Python

class Dog extends Animal { function bark() { parent::bark(); }}

class Dog(Animal): def bark(self): super(Dog, self).bark() # or Animal.bark(self)

•組み込み関数super()を使って呼び出す

•クラス名を指定する必要がある (←ダサい)

•「parent::」で親クラスのメソッドを呼び出す

•クラス名を指定する必要がない

130

Page 131: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

多重継承PHP Python

## なし、## インターフェースで代用

class Animal(object): def bark(self): print "Bow wow"class Entity(object): def save(self): print "insert into ..."class Dog(Animal, Entity): pass

131

Page 132: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

isinstancePHP Python

$u instanceof User

$u instanceof User ||$u instanceof Animal

isinstance(u, User)

isinstance(u, (User, Animal))

• instanceof は演算子

• isinstance() は組込関数•タプルを使って複数のクラスを指定可能

132

Page 133: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

アクセス制限PHP Python

public class User { private $name; public function __construct($name) { $this->name = $name; } public function getName() { return $this->name; }}

class User(object): def __init__(self, name): self._name = name self.__name = nameu = User("Haruhi")print u.__dict__ #=> {'_name': 'Haruhi', # '_User__name': 'Haruhi'}

• '_' で始まっていれば非public•紳士協定であり強制力はない• '__' で始まるとクラス名が自動付加 (Name Mangling)

• 'public'、'protected'、 'private' が利用可能

133

Page 134: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

クラス変数、クラスメソッドPHP Python

class User { static $table = "users"; function find($id) { $t = User::$table; echo "select from $t ..."; }}User::find(123);

class User(object): table = "users" @classmethod def find(cls, id): t = cls.table print "select from %s ..." % t

User.find(123)

•デコレータを使う (後述)•第1引数はクラスオブジェクト

•予約語「static」を使う•「$this」にアクセスできないメソッド

134

Page 135: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

インスタンスからクラスを参照PHP Python

class User { static $table = "users"; function m1() { echo static::$table; }}$user = new User();$user->m1(); #=> users

class User(object): table = "users" def m1(self): print self.__class__.table

user = User()user.m1() #=> users

•クラスオブジェクトの属性として参照

•「static::」または「self::」をつける

135

Page 136: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

スタティックメソッドPython

class Foo(object): @staticmethod def hello(name='World'): print 'Hello %s!' % name

Foo.hello("Mikuru") #=> Hello Mikuru!obj = Foo()obj.hello("Yuki") #=> Hello Yuki!

•クラスからもインスタンスからも呼び出せる•インスタンス変数やクラス変数にはアクセス不可

136

Page 137: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

アクセッサPython

class User(object): def __init__(self, name): self.__name = name def _getname(self): return self.__name def _setname(self, name): msg = "'name' is read-only" raise TypeError(msg) name = property(_getname, _setname)

u = User("Yuki")print u.__dict__ #=> {'_User__name': 'Yuki'}print u.name #=> Yukiu.name = "Nagato" #=> TypeError: 'name' is read-only

name属性は読み取り専用になっている

• property() に getter と setter を指定する

137

Page 138: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

型(type)Python

type("foo") #=> <type 'str'>

isinstance("foo", str) #=> Trueisinstance(u"f", unicode) #=> Trueisinstance([1, 2], list) #=> Trueisinstance({'a':1}, dict) #=> True

isinstance(val, (tuple, list))isisntance(val, (str, unicode)) # or isinstance(val, basestring)

• list や str は、クラスに似た「型(type)」である•「型」は組み込み関数 type() で取り出せる

138

Page 139: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

インスタンスとクラスの仕組み

【関連ドキュメント】

• チュートリアル: 9. クラスhttp://www.python.jp/doc/release/tut/node11.html

• 言語仕様リファレンス: 7.7 クラス定義http://www.python.jp/doc/release/ref/class.html

139

Page 140: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

オブジェクト指向言語の仕組み

Variable

Instance obj

Class obj

Class obj

x: 10y: 20

Method Tbl

Method Tbl

m4

m2m3

m3

m1m2

func ( ) { .....}

Z: 123

Z: 456

Function

func ( ) { .....}

func ( ) { .....}

self

self

self

140

Page 141: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

インスタンスとクラスの関係

x: 10y: 20

z: 30g: <func>

f: <func>g: <func>

変数 インスタンス

辞書

辞書

辞書

クラス

クラス

.__dict__.__class__ .__dict__

.__base__

object

141

Page 142: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

インスタンスとクラス変数Python

class User(object): name = "SOS" def hello(self): print self.name

print User.name #=> SOSprint User.hello #=> <unbound method User.hello>u = User()print u.nameprint u.hello #=> <bound method User.hello of ...>

•インスタンスメソッドはクラス属性

インスタンスと結びついている

インスタンスと結びついてない

142

Page 143: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

インスタンスとクラス変数Python

class User(object): name = "SOS"

user = User()print user.name #=> SOS

user.name = "Haruhi"print user.name #=> Haruhi

delattr(user, 'name')print user.name #=> SOS

インスタンス変数が未設定のときはクラス変数の値が使われる

インスタンス変数はクラス変数より優先される

インスタンス変数を削除すると元に戻る

143

Page 144: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

bound / unbound メソッドPython

class User(object): def hello(self): print self.name

u = User()u.name = "Kyon"u.hello() #=> KyonUser.hello(u) #=> Kyon

f = u.hello; f() #=> Kyon

• u.hello() と User.hello(u) は (ほぼ) 同等

• u.hello() は bound メソッドの呼び出し

• User.hello() は unbound メソッドの呼び出し、第1引数に self が必要

• bound メソッドは変数に代入して呼び出すことが可能

144

Page 145: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

関数とインスタンスメソッドPython

def hello(self): print self.nameprint hello #=> <function hello>

class User(object): passUser.hello = helloprint User.hello #=> <unbound method User.hello>u = User()print u.hello #=> <bound method User.hello>

普通の関数をクラス属性に代入するだけで、インスタンスメソッドとして利用可能

これは普通の関数

145

Page 146: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

インスタンスごとのメソッドPython

def hello(self): print self.name

class User(object): pass

•そのインスタンスだけのメソッドを設定するには、 bound method を設定するだけでよい

• types.MethodType でラップすると bound method を生成できる

import typesu = User(); u.name = "Mikuru"u.hello = types.MethodType(hello, u)print u.hello #=> <bound method>u.hello() #=> Mikuru

146

Page 147: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

__slots__Python

class User(object): __slots__ = ('name', 'age') def hello(self): print "Hello %s!" % self.name

u = User()u.name = "Haruhi"u.hello() # Hello Haruhi!u.phone = "090-..." # AttributeErrorprint u.__dict__ # AttributeError

• __slots__ に指定した属性のみ利用可能、それ以外はAttributeError

•デフォルト値としてのクラス属性は参照されなくなる

•インスタンスはdictベースではなく構造体ベースになる

•子クラスには引き継がれない

147

Page 148: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

ファイル操作

【関連ドキュメント】

• チュートリアル: 7.2 ファイルを読み書きするhttp://www.python.jp/doc/release/tut/node9.html#SECTION009200000000000000000

• ライブラリリファレンス: 3.9 ファイルオブジェクトhttp://www.python.jp/doc/release/lib/bltin-file-objects.html

148

Page 149: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

ファイルを読み込むPHP Python

$f = fopen("a.txt", "r");echo fread($f, filesize("a.txt"));fclose($f);

echo file_get_contents("a.txt");

f = open("a.txt")print f.read()f.close()

print open("a.txt").read()

with open("a.txt") as f: print f.read()

CPythonのGCはリファレンスカウント方式なので、参照されなくなったファイルオブジェクトは自動的にcloseされる with文を使うとより安全

149

Page 150: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

ファイルに書き込むPHP Python

$f = fopen("file.txt", "w");fwrite($f, "ABC");fclose($f);

file_puts_contents("file.txt", "ABC");

f = open("file.txt", "w")f.write("ABC\n")f.close()

open("file.txt", "w").write( "ABC")

with open("file.txt", "w") as f: f.write("ABC")

with文を使うとより安全

150

Page 151: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

文字コードを指定して読み書きPython

import codecsf = codecs.open("file.txt", encoding="utf8")x = f.read() # strではなくunicodeを返すprint type(x) #=> <type 'unicode'>s = x.encode('utf8') # unicodeをstrへ変換f.close()

151

Page 152: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

1行ずつ読み込むPHP Python

$f = fopen("file.txt", "r");$line = fgets($f);while ($line !== FALSE) { var_export($line); $line = fgets($f);}fclose($f);

for line in open("file.txt"): print repr(line)

## またはwith open("file.txt") as f: for line in f: print repr(line)

152

Page 153: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

ファイルが存在するかどうかPHP Python

file_exists("file_or_dir");is_file("file.txt");is_dir("/tmp");

import osos.path.exists("file_or_dir")os.path.isfile("file.txt")os.path.isdir("/tmp")

153

Page 154: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

ファイル操作PHP Python

rename("old", "new")unlink("file")mkdir("dir")rmdir("dir")

import osos.rename("old", "new")os.unlink("file")os.mkdir("dir")os.rmdir("dir")

154

Page 155: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

ファイル名操作PHP Python

$s = "path/to/file";basename($s);dirname($s);

glob('*.txt');

import oss = 'path/to/file'os.path.basename(s)os.path.dirname(s)

import globglob.glob('*.txt')

155

Page 156: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

例外処理

156

Page 157: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

基本構文Python

try: raise Exception("message")except TypeError, ex: print exexcept (KeyError, NameError), ex: print exfinally: pass タプルを使って複数のエ

ラークラス名を指定可能

157

Page 158: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

raisePython

raise NameError('Haruhi: no such student.') # 例外オブジェクトraise NameError, 'Haruhi: no such student.' # クラスと引数raise # 例外を再送

try: import sosexcept ImportError: logging.info('sos: module not found.') raise # 例外をログに記録してから再送

158

Page 159: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

else節Python

try: f = open('file.txt')except Exception, ex: print str(ex)else: print f.read()finally: if f: f.close()

•例外が発生しなかったときだけ else 節が実行される

159

Page 160: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

例外オブジェクトPython

try: raise Exception('mesg', 123, True)except Exception, ex: print ex.message print ex.args #=> ('mesg', 123, True) arg1, arg2, arg3 = ex # 多重代入が可能 print [arg1, arg2, arg3] #=> ['mesg', 123, True]

160

Page 161: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

例外クラスPython

class HttpError(Exception): pass

class Http404NotFound(HttpError): status = '404 Not Found' def __init__(self, url): self.url = url self.message = 'Page Not Found' def __str__(self): return self.message

• Exceptionクラスを継承する•種類ごとに基底クラスを定義するとよい

• __str__()を適切にオーバーライドするとよい (str(ex) でメッセージが表示されるようになる)

161

Page 162: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

主な例外クラス (1)Python

# SynstaxError … 文法が間違っている、またはコードに日本語が# 含まれているのにマジックコメントがないTrue && True #=> SyntaxError: invalid syntax

# TypeError … データや引数の型または数が間違っているlist1 = ['Haruhi','Mikuru','Yuki']list1["3"] #=> TypeError: list indices must be integerslist1.append('Kyon', 'Itsuki') #=> TypeError: append() takes exactly # one argument (2 given)

162

Page 163: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

主な例外クラス (2)Python

# ValueError … 型は正しいが値として間違っているf = open('members.txt')f.close()f.read() #=> ValueError: I/O operation on closed file

# UnicodeEncodeError … ユニコード関連のエラーprint u'ハルヒ'.encode('utf-8')print u'ハルヒ' #=> UnicodeEncodeError: 'ascii' codec can't # encode characters in position 0-2: ordinal # not in range(128)

163

Page 164: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

主な例外クラス (3)Python

# NameError … 変数や関数が存在しないx = haruhi #=> NameError: name 'haruhi' is not defined

# AttributeError … 属性やメソッドが存在しない、# または変数がNoneであるclass Kyon(object): passKyon().megane #=> AttributeError: 'Kyon' object has # no attribute 'megane'None.megane #=> AttributeError: 'NoneType' object has # no attribute 'megane'

164

Page 165: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

主な例外クラス (4)Python

# KeyError … 辞書のキーが存在しない{'a':1}['b'] #=> KeyError: 'b'

# IndexError … リストやタプルで添字が範囲外list1 = ['Haruhi','Mikuru','Yuki']list1[3] #=> IndexError: list index out of range

# IOError … ファイルが存在しない、アクセス権限がない、等open('haruhi.txt') #=> IOError: [Errno 2] No such file # or directory: 'haruhi.txt'

165

Page 166: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

主な例外クラス (5)Python

# ImportError … 存在しないモジュールをimportしようとしているimport sos #=> ImportError: No module named sos

166

Page 167: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

組み込み例外クラスの一覧Python

## 組み込みの例外クラスをすべて表示するfor name, val in vars(__builtins__).iteritems(): if isinstance(val, type) and issubclass(val, Exception): print name # 名前だけ表示 print "%s: %s" % (name, val.__doc__) # ドキュメントも表示

167

Page 168: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

正規表現

【関連ドキュメント】

• ライブラリリファレンス: re - 正規表現http://www.python.jp/doc/release/lib/module-re.html

• チュートリアル: 10.5 文字列のパターンマッチングhttp://www.python.jp/doc/release/tut/node12.html#SECTION0012500000000000000000

168

Page 169: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

パターンマッチPHP

Python

$s = '<img src="logo.gif">';if (preg_match('/src="(.*?)"/', $s, $m)) echo $m[0], " ", $m[1]; #=> src="logo.gif" logo.gif

import res = '<img src="logo.gif">'m = re.search(r'src="(.*?)"', s)if m: print m.group(0), m.group(1) #=> src="logo.gif" logo.gif

• re.match()は先頭にマッチ• re.search()は途中にもマッチ

169

Page 170: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

オプション指定PHP

Python

$s = '<h1>Title</h1>';if (preg_match('/^<h1>(.*?)<\/h1>$/msi', $s, $m)) echo $m[1];

import res = '<h1>Title</h1>'m = re.search(r'^<h1>(.*?)</h1>$', s, re.M|re.S|re.I)if m: m.group(1)

• re.search()の第3引数にオプション指定

170

Page 171: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

置換PHP

Python

$s = '<img src="logo.gif">';echo preg_replace('/(\w+\.gif)/', 'img/\1', $s); #=> <img src="img/logo.gif">

import res = '<img src="logo.gif">'print re.sub(r'(\w+\.gif)', r'img/\1', s) #=> <img src="img/logo.gif">

• re.sub() の第4引数に置換回数を指定できる (例: 1 なら最初の1回だけ置換)

171

Page 172: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

コールバックつき置換PHP

Python

$ESC = array('<'=>'&lt;', '>'=>'&gt;', '&'=>'&amp;');function f($m) { global $ESC; return $ESC[$m[0]]; }echo preg_replace_callback('/[<>&]/', 'f', '<A&B>');

import reESC = {'<':'&lt;', '>':'&gt;', '&':'&amp;'}f = lambda m: ESC[m.group(0)]print re.sub(r'[<>&]', f, '<A&B>') #=> &lt;A&amp;B&gt;

•コールバック関数の実行結果で置換される

172

Page 173: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

繰り返しマッチPHP

Python

$s = file_get_contents("index.html");preg_match_all('/href="(.*?)"/', $s, $arr);foreach ($arr[0] as $url) echo $url, "\n";

import res = open("index.html").read()for m in re.finditer(r'href="(.*?)"', s): print m.group(1) • re.findall()はリストを返す

• re.finditer()はイテレータ(後述)を返す

173

Page 174: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

分割PHP

Python

$s = '/public/img/logo.gif';$arr = preg_split('/\//', $s);var_export($arr); #=> array(0=>'', 1=>'public', 2=>'img', 3=>'logo.gif')

import res = '/public/img/logo.gif'list1 = re.split(r'/', s)print list1 #=> ['', 'public', 'img', 'logo.gif']

• re.split()の第3引数に最大分割数を指定できる

174

Page 175: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

コンパイルPHP

Python

## 該当機能なし

import res = '<h1>Title</h1>'pattern = re.compile(r'^<h1>(.*?)</h1>$', re.M|re.S|re.I)m = pattern.search(s)if m: m.group(1) •正規表現を事前にコンパイル可能

•実行効率は多少よくなる

175

Page 176: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

メソッド一覧reパッケージ patternオブジェクト

re.match(rexp, str)re.search(rexp, str)re.sub(rexp, repl, str, n=0)re.subn(rexp, repl, str, n=0)re.split(rexp, str, n=0)re.findall(rexp, str)re.finditer(rexp, str)re.compile(rexp, repl, str)re.purge(rexp, repl, str)re.escape(rexp, repl, str)

pattern.match(str)pattern.search(str)pattern.sub(repl, str, n=0)pattern.subn(repl, str, n=0)pattern.split(str, n=0)pattern.findall(str)pattern.finditer(str)---

pattern = re.compile(rexp)

176

Page 177: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

高階関数、クロージャ

【関連ドキュメント】

• チュートリアル: 4.6 関数を定義するhttp://www.python.jp/doc/release/tut/node6.html#SECTION006600000000000000000

• 言語仕様リファレンス: 4.1 名前づけと束縛 (naming and binding)http://www.python.jp/doc/release/ref/naming.html

• 言語仕様リファレンス: 7.6 関数定義http://www.python.jp/doc/release/ref/function.html

177

Page 178: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

高階関数とは?✤ 関数をデータとして扱う関数

✤ 関数を引数とする関数✤ 関数を戻り値とする関数

Python

def f(n): return n*n # 関数の定義f = lambda n: n*n # 関数の作成

•「関数を定義する」=「関数オブジェクトを作成 (して変数に代入) する」

•関数オブジェクトをデータとして扱える

178

Page 179: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

よくある光景Python

def map_square(items): L = [] for x in items: L.append(x * x) return L

nums = [1, 2, 3]print map_square(nums) #=> [1, 4, 9]

•一部の処理が違うだけで、あとは一緒の関数

def map_label(items): L = [] for x in items: L.append("(%s)" % x) return L

nums = [1, 2, 3]print map_label(nums) #=> ['(1)', '(2)', '(3)']

179

Page 180: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

関数を引数にとる関数: mapPython

def map(func, items): L = [] for x in items: L.append(func(x)) return L

•違う処理を関数で与える• map() は組み込み関数として提供済

nums = [1, 2, 3]f = lambda n: n*nprint map(f, nums)

f = lambda n: '(%s)' % nprint map(f, nums)

180

Page 181: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

関数を引数にとる関数: filterPython

def filter(func, items): L = [] for n in items: if func(n): L.append(n) return L

•条件を満たす要素だけを集める関数

• filter() は組み込み関数として提供済

nums = [1, 7, 3, 2, 0, 5, 0, 8]print filter(lambda n: n % 2, nums) #=> [1, 7, 3, 5]

print filter(lambda n: n > 5, nums) #=> [7, 8]

181

Page 182: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

関数を引数にとる関数: maxPython

def max_by(func, items): is_first = True for x in items: v = func(x) if is_first: max, item = v, x! is_first = False elif max < v: max, item = v, x return item

•評価関数が最大になる要素を返す•組み込み関数 max(items, key=func) が提供済

SOS = [('Haruhi', 'C'), ('Mikuru', 'E'), ('Yuki', 'A'), ]f = lambda x: x[1]print max_by(f, SOS) #=> ('Mikuru', 'E')

182

Page 183: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

関数を引数にとる関数: reducePython

def reduce(func, items, init): accum = init for x in items: accum = func(accum, x) return accum

•累積値 (accum) と要素 (x) を使って何らかの処理を行う関数

•組み込み関数として提供済

nums = xrange(1, 10+1)func = lambda a, x: a+xprint reduce(func, nums, 0) #=> 55

183

Page 184: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

関数を返す関数Python

odd, even = "#FCC", "#CCF"def oddeven(): def func(n): if n % 2 == 1: return odd else: return even return func

f = oddeven()print f(1) #=> #FCCprint f(2) #=> #CCFprint f(3) #=> #FCC

関数内部で作成した関数を返す

普通に定義した関数と同様に利用可能

•「関数を定義する」=「関数オブジェクトを作成 (して変数に代入) する」

184

Page 185: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

外側のローカル変数を参照Python

def oddeven(odd, even): def func(n): if n % 2 == 1: return odd else: return even return func

f1 = oddeven("red", "blue")print f1(1) #=> redprint f1(2) #=> blueprint f1(3) #=> red

f2 = oddeven("#FCC", "#CCF")print f2(1) #=> #FCCprint f2(2) #=> #CCFprint f2(3) #=> #FCC•グローバル変数を使わない

ので、挙動の異なる関数を多数作成できる

185

Page 186: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

クロージャ✤ 関数+外側のローカル変数

✤ 内側の関数オブジェクトが生存する間は、それが参照している、外側のローカル変数も生存する(すぐには消えない)。

Python

def oddeven(odd, even): def func(n): if n % 2 == 1: return odd else: return even return func

f1 = oddeven('#FCC', '#CCF')print f1(1), f1(2), f1(3)f2 = oddeven('red, 'blue')print f2(1), f2(2), f2(3)

•内側の関数が存命中なので、変数oddとevenも存命中

186

Page 187: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

クロージャではない例Python

def oddeven(odd, even): def func(n): if n % 2 == 1: return '#FCC' else: return '#CCF' return func

odd, even = '#FCC', '#CCF' def oddeven(): def func(n): if n % 2 == 1: return odd else: return even return func

•どちらも、外側のローカル変数を参照していないので、クロージャではない

187

Page 188: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

変数スコープPython

def outer(): # グローバル変数 a = b = c = 0 # outer()のローカル変数 d = [] # 同上 def inner(): # 同上 print a # 同上 b = 1 # inner()のローカル変数 nonlocal c # Python 3.0以降で利用可能 c = 1 # outer()のローカル変数(Python 3.0以降) d[0] = 1 # outer()のローカル変数 return inner # 同上

188

Page 189: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

引数の部分適用✤ N個の引数を持つ関数にM個の引数を与えることで、

(N-M)個の引数を持つ関数を新たに作成することPython

def map_square(items): func = lambda x: x*x return map(func, items)

## 変形func = lambda x: x*xdef _map(items): return map(func, items)map_square = _map

## さらに変形def map_builder(func): def _map(items): return map(func, items) return _mapmap_square = \ map_builder(lambda x: x*x)map_increase = \ map_builder(lambda x: x+1)

部分適用を行う関数

189

Page 190: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

デコレータ

【関連ドキュメント】

• 言語仕様リファレンス: 7.6 関数定義http://www.python.jp/doc/2.5/ref/function.html

190

Page 191: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

デコレータ✤ 関数を修飾するための機能

✤ 実体は、関数を受け取り関数を返すような関数

Python

class Foo(object): @classmethod def hello(cls): print "Hello World!" ## これは次と同じ hello = classmethod(hello)

class Foo(object): @foo(123, "bar") def hello(cls): print "Hello World!" ## これは次と同じ func = foo(123, "bar") hello = func(hello)

引数指定も可能

191

Page 192: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

サンプル: TemplateMethod(1)Python

def with_dummy(func): def newfunc(self): open('A.txt', 'w') \ .write('AAA') # setup try: func(self) # do test finally: os.unlink('A.txt') # teardown return newfunc

## 使用例@with_dummydef test_1(self): # ... A.txt を使ったテスト...

@with_dummydef test_2(self): # ... A.txt を使ったテスト...

もとの関数を呼び出すような新しい関数を生成して返す

デコレータは、関数を受け取り、関数を返すような関数

192

Page 193: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

サンプル: TemplateMethod(2)Python

def with_dummy(fname, data): def deco(func): def newfunc(self): open(fname, 'w') \! .write(data) try: func(self) finally: os.unlink(fname) return newfunc return deco

## 使用例@with_dummy('x.txt', 'XXX')def test_1(self): # ... y.txt を使ったテスト...

@with_dummy('y.txt', 'YYY')def test_2(self): # ... y.txt を使ったテスト...

生成したデコレータを返す

デコレータを生成する関数

193

Page 194: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

サンプル: メモ化デコレータ(1)Python

def memoize(f): memo = {} def g(n): if n not in memo: memo[n] = f(n) return memo[n] return g

## 使用例@memoizedef fib(n): if n <= 2: return 1 else: return fib(n-1)+fib(n-2)

print fib(50) # 爆速!

デコレータは、関数を1つ受け取り、かつ関数を返すような関数

f()の計算結果を保存し、再利用する

194

Page 195: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

サンプル: メモ化デコレータ(2)Python

## 任意個の引数をとれるよう拡張def memoize(f): memo = {} def g(*args): if args not in memo: memo[args] = f(*args) return memo[args] return g

## 使用例@memoizedef tak(x, y, z): if x <= y: return y else: return tak(tak(x-1, y, z), tak(y-1, z, x), tak(z-1, x, y))

print tak(13, 5, 0) #=>13

任意個の引数を受け取り、…

それらをまるごとf()に渡す

引数が複数個ある関数にも適用可能

argsはタプルなので辞書のキーとして利用可能

195

Page 196: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

サンプル:任意の引数へ対応Python

## 任意の関数の戻り値を## 2倍するデコレータdef cheat(f): def g(*args, **kwargs): v = f(*args, **kwargs) return 2*v return g

## 使用例@cheatdef add(x,y): return x+yprint add(3, y=5) #=> 16

受け取ったすべての引数を、キーワード引数も含めて別の関数にそのまま渡す

引数のどんな渡し方でも大丈夫

196

Page 197: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

サンプル:デコレータ生成関数Python

def cheat(n): def _cheat(f): def g(*args, **kwargs): v = f(*args, **kwargs) return n * v return g return _cheat

## 使用例@cheat(3)def add(x,y): return x+yprint add(3, 5) #=> 24

デコレータを生成する関数

デコレータを返す

デコレータ

197

Page 198: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

イテレータ

【関連ドキュメント】

• チュートリアル: 9.8 イテレータ (iterator)http://www.python.jp/doc/release/tut/node11.html#SECTION0011800000000000000000

• ライブラリリファレンス: 3.5 イテレータ型http://www.python.jp/doc/release/lib/typeiter.html

198

Page 199: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

イテレータとは?✤ 「繰り返し」という概念を抽象化

✤ 「次の値を取得する」と「次の値がなければ終了する」✤ 違うデータ構造に対し同一の方法で繰り返しが可能になる

Python

list1 = [10, 20, 30]it = list1.__iter__()print it.next() #=> 10print it.next() #=> 20print it.next() #=> 30print it.next() #=> StopIteration

イテレータを生成

終了時に例外を発生

next()で次の値を取得199

Page 200: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

イテレータとfor文Python

## これは次と (だいたい) 同じit = [10, 20, 30].__iter__()try: while True: item = it.next() print itemexcept StopIteration: pass

• for文は内部でイテレータを生成し実行している

for item in [10, 20, 30]: print item

200

Page 201: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

イテレータとfor文 (cont)Python

## これは次と (だいたい) 同じit = open('file.txt').__iter__()try: while True: line = it.next() print line,except StopIteration: pass

for line in open('file.txt'): print line,

201

Page 202: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

サンプル: ListItemsPython

class ListItems(object): def __init__(self, list1): self.list = list1 self.i = -1 def __iter__(self): return self def next(self): self.i += 1 if self.i >= len(self.list): raise StopIteration() item = self.list[self.i] return "<li>%s</li>" % item

## 使用例list1 = ['foo', 'bar', 'baz']for s in ListItems(list1): print s

## 実行結果<li>foo</li><li>bar</li><li>baz</li>

202

Page 203: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

ジェネレータ

【関連ドキュメント】

• チュートリアル: 9.9 ジェネレータ (generator)http://www.python.jp/doc/release/tut/node11.html#SECTION0011900000000000000000

• 言語仕様リファレンス: 6.8 yield 文http://www.python.jp/doc/release/ref/yield.html

203

Page 204: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

通常の関数Python

## 通常の関数def f1(): x = 10 return x x += 1 return x x += 1 return x

print f1() #=> 10print f1() #=> 10print f1() #=> 10print f1() #=> 10

•呼び出すごとに最初から実行される

•ローカル変数の値は保存されない

204

Page 205: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

ジェネレータPython

## ジェネレータ関数def ex1_gen(): x = 10 yield x x += 1 yield x x += 1 yield x

## ジェネレータオブジェクトを生成g = ex1_gen()print g.next() #=> 10print g.next() #=> 11print g.next() #=> 12print g.next() #=> StopIteration

•再開可能な関数 (resumable function)• yield で実行を一次中断し、.next() で再開(RPGのセーブと類似)

•最後に例外StopIterationが発生

205

Page 206: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

サンプル:フィボナッチ数列Python

def fib(): x, y = 1, 1 while True: yield x x, y = y, x+y

g = fib()print g.next() #=> 1print g.next() #=> 1print g.next() #=> 2print g.next() #=> 3print g.next() #=> 5print g.next() #=> 8print g.next() #=> 13print g.next() #=> 21

ジェネレータ関数 ジェネレータオブジェクト

再帰を使わないので爆速

206

Page 207: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

サンプル:cycle()Python

def cycle(*args): i = 0 n = len(args) while True: yield args[i] i += 1 if i == n: i = 0

g = cycle("odd", "even")print g.next() #=> oddprint g.next() #=> evenprint g.next() #=> odd

f = cycle("odd", "even").nextprint f() #=> oddprint f() #=> evenprint f() #=> odd

ジェネレータ関数 ジェネレータオブジェクト

207

Page 208: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

ジェネレータとイテレータPython

g = ex1_gen() print repr(g) #=> <generator at 0x13c0200>print repr(g.__iter__()) #=> <generator at 0x13c0200>

• .__iter__() は自分自身を返す• .__iter__() と .next() があるので

for 文で使える

for val in ex1_gen(): print val

## 次とほぼ同じg = ex1_gen().__iter__()try: while True: print g.next()except StopIteration: pass

208

Page 209: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

利点:長いリストを作らずに済むPython

range(1, 5) #=> [1,2,3,4]xrange(1,5) #=> xrange

for i in range(1, 1000001): print ifor i in xrange(1, 1000001): print i

• range()は長いリストを生成する(=メモリを大量に消費)

• xrange()はxrangeオブジェクトをひとつ作成するだけ(=メモリ消費量が少ない)

209

Page 210: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

利点:「無限」を扱えるPython

## .next() が呼び出される## 限りフィボナッチ数列## を無限に計算し続けるdef fib_gen(): x, y = 0, 1 while True: x, y = y, x+y yield x

## フィボナッチ数列を## 無限に出力し続けるg = fib_gen()while True: print g.next()

210

Page 211: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

利点: '処理' と '条件' を分離Python

• generatorなしだと、「計算」や「処理」と、ループの終了判定とが混在=終了条件が異なれば、「計算」や「処理」をもう一度書かなければいけない

## 1000個までのfib数列x, y = 0, 1i = 0while i < 1000: i += 1 x, y = y, x+y print x

## 1000 未満までのfib数列x, y = 0, 1x, y = y, x+ywhile x < 1000: print x x, y = y, x+y

211

Page 212: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

利点: '処理' と '条件' を分離Python

## .next() が呼び出される## 限りフィボナッチ数列## を無限に計算し続けるdef fib_gen(): x, y = 0, 1 while True: x, y = y, x+y yield x

•「無限」が扱える=終了条件を指定しなくてよい (別途指定できる)=ループの「処理」と「終了条件」とを分離できる

## 1000個g = fib_gen()i = 0while i < 1000: i += 1 n = g.next() print n

## 1000 未満g = fib_gen()n = g.next()while n < 1000: print n n = g.next()

212

Page 213: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

ジェネレータ式Python

g = ( (i, i*i) for i in xrange(1, 5) )print g #=> <generator object>print g.next() #=> (1, 1)print g.next() #=> (2, 4)print g.next() #=> (3, 9)print g.next() #=> (4, 16)print g.next() #=> StopIteration

•丸カッコの中に内包表記 (list complehension) を書くと、それだけでジェネレータになる

213

Page 214: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

ジェネレータ式 (cont)Python

names = ['Haruhi', 'Mikuru', 'Yuki']tuples = [ (s, len(s)) for s in names ]print tuples #=> [('Haruhi', 6), ('Mikuru', 6), ('Yuki', 4)]d1 = dict(tuples)print d1 #=> {'Haruhi': 6, 'Mikuru': 6, 'Yuki': 4 }d2 = dict( (s, len(s)) for s in names )print d2 #=> {'Haruhi': 6, 'Mikuru': 6, 'Yuki': 4 }

•引数のカッコの中にジェネレータ式が書ける•リストを引数にとる関数は、ジェネレータも受け付けることが多い

214

Page 215: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

.next()と.send()

## ジェネレータ yield 123

yield 456

## メインプログラムval = g. next() # val == 123

val = g.next() # val == 456

val = g.next() # StopIterationStopIteration

•ジェネレータからメインへは値を渡せる (yield の引数)•その逆は?

215

Page 216: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

.next()と.send() (cont)

## ジェネレータ ret = yield 123

ret = yield 456

## メインプログラムval = g. next() # or .send(None) # val == 123

val = g.send('aaa') # val == 456

val = g.send('bbb') # StopIteration

# ret == 'aaa'

# ret == 'bbb'

StopIteration

• .send() を使う (.send()の引数がyieldの戻り値)• .send(None) は .next() と同じ

216

Page 217: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

ジェネレータ: サンプルPython

# -*- coding: utf-8 -*-def yome_gen(): ans = yield '(a)元気な子 (b)おとなしい子' if ans == 'a': ans = yield '(a)ツンデレ (b)笑い上戸' yome = ans == 'a' and 'ハルヒ' or '鶴屋さん' elif ans == 'b': ans = yield '(a)巨乳 (b)貧乳' yome = ans == 'a' and 'みくる' or '長門' raise StopIteration(yome)

• yield で値 (=質問文) を返しながら、同時に別の値 (=ユーザ回答) を受け取っている

217

Page 218: Python4PHPer - PHPユーザのためのPython入門 (Python2.5)

ジェネレータ: サンプル (cont)Python

g = yome_gen()ans = Nonetry: while True: question = g.send(ans) print question, ' >>', ans = raw_input()except StopIteration, ex: yome = ex.args[0] print 'おすすめは', yome

## 実行例

(a)元気な子 (b)おとなしい子 >> a

(a)ツンデレ (b)笑い上戸 >> bおすすめは 鶴屋さん

g.send(None) は g.next() と同じ

• send() で値 (=ユーザ回答) を渡しながら、かつ戻り値 (=質問文) を受け取っている

218