x,y,z = 1,2,3 first, second = second, first a = b = 123
if x < 5 or (x > 10 and x < 20):
print "The value is OK."
if x < 5 or 10 < x < 20:
print "The value is OK."
for i in [1,2,3,4,5]:
print "This is iteration number", i
x = 10
while x >= 0:
print "x is still not negative."
x = x-1
# Print out the values from 0 to 99 inclusive.
for value in range(100):
print value
x = input("Please enter a number: ")
print "The square of that number is", x*x
- **注意:**
- もし、inputで文字列を受け付けたいなら、ユーザーは引用符で明示的 に文字列を括る必要があります。Pythonでは、文字列は引用符か二重引用符で 括られているからです。
name = ["Cleese", "John"] x = [[1,2,3],[y,z],[[[]]]]
print name[1], name[0] # Prints "John Cleese" name[0] = "Smith"
x = ["spam","spam","spam","spam","spam","eggs","and","spam"] print x[5:7] # Prints the list ["eggs","and"]
{ "Alice" : 23452532, "Boris" : 252336,
"Clarice" : 2352525, "Doris" : 23624643}
person = { 'first name': "Robin", 'last name': "Hood",
'occupation': "Scoundrel" }
person['last name'] = "of Locksley"
- **次の一歩:**
- 抽象化をしよう。コードひとつひとつに名前を付けて、二つのパラ メーターと一緒に呼び出してみましょう。そのことを他の言い方でいうと?(抽ー 象ー化ー!) 私たちは今、関数(または、"手続き")を定義してみたいです。で、 どうすればいいでしょう?単に、以下のようにdefキーワードーを使えばいいだけ です。
def square(x):
return x*x
print square(2) # Prints out 4
def change(some_list):
some_list[1] = 4
x = [1,2,3]
change(x)
print x # Prints out [1,4,3]
def nochange(x):
x = 0
y = 1
nochange(y)
print y # Prints out 1
もしあなたが、関数の一般的な使い方を知っているのなら、Pythonで関数につ いて知らなければいけない基本的な事を、既に知っている事になります。(も ちろん、そうです…returnキーワードは関数の実行を停止して、与えられた値 を返すようになっています。)
知っておくと便利かもしれない事のひとつは、実は、Pythonでは関数も値だと いう事です。つまり、あなたがsquareという関数を持っていたら、こうする事 ができます。
queeble = square print queeble(2) # Prints out 4
関数を引数なしで呼び出すには、doit()であってdoitでないという事を覚えて おいて下さい。後者の場合は、例で見たように関数自身が返され、結果が返さ れる訳ではありません。(これはメソッドオブジェクトにも当てはまります… 後の章を見て下さい)
私はこの章では、あなたが既にオブジェクト指向プログラミングがどういった ものかということを知っている事として話を進めていきます。(もしそうでな いなら、この章の内容はあまりしっくり来ないかもしれません。でも問題ない です…オブジェクトなしで始めたらいいだけの事ですから:))Pythonではクラ スをclassというキーワードで定義します(あまりの自明さに、めまいが…)。 では例を見ましょう。
class Basket:
# Always remember the *self* argument
def __init__(self,contents=None):
self.contents = contents or []
def add(self,element):
self.contents.append(element)
def print_me(self):
result = ""
for element in self.contents:
result = result + " " + `element`
print "Contains:"+result
- **ここでの新事項:**
-
-
全てのメソッド(オブジェクトの中の関数)は引数のリストの1番目にオ ブジェクト自身の入った引数を受けとる。(その引数は、習慣的にselfと いう名で呼ばれている)
-
メソッドは、以下のように呼び出す: object.method.(arg1,arg2)
-
init__のような名前のメソッドは、特別なもので、必ず定義される。 init__というはクラスの"コンストラクタ"の名前で、例えば、あなたがイ ンスタンスを作る時に呼び出される。
-
関数呼び出しの時に埋めなくてもよい引数を作ることや、引数にデフォ ルトの値を与えたりする事ができる(関数の章で触れたように)。デフォル ト引数を使いたければ以下のようにする。
def spam(age=32): ...
この例では、spamは0から1個のパラメーターとともに呼ばれる。もし何も 与えられなければ、ageパラメーターの値は32になる。
-
この例で使われた"ショート・サーキット・論理"は少し難しいです…後 で説明しましょう。
-
逆引用符(バッククウォート)は、オブジェクトを、説明の文字列に変換 する。(つまり、elementの中身が数字の1なら、
elementというのは、1 と同じことで、'element'というのはただの文字列です。) -
足し算の記号"+"はリストの結合にも使われる。文字列というのは実は、 文字のリストである。(このことは、文字列にもインデックス参照やスラ イス、len関数を使える事を意味している。クールでしょ?)
-
Pythonでは、どのメソッドも変数も(privateのようには)プロテクトされてい ません。カプセル化はプログラミングスタイル以上のものです。(もしあなた が、"本当に"そういったものを必要としているなら、ネーミング・コンベンショ ン(命名の規則)が同様のプライバシーを提供してくれます:))
では次は、ショート・サーキット論理についてです…
Pythonの中の変数は全て、論理値として使う事ができます。[]、0、""、None のような"空"の値は、偽を意味し、その他の値の時([0]、1、"Hello, world" など)は、真を意味します。
a and bのような論理式は、次のような動作をします。まず、aが真かどうか確 かめます。もしそうで"ない"なら、単純にaを返します。もし"そう"なら、bを 返します(これが式の真の値を返すから)。a or bという式の仕組みは、もしa が真ならそれを返し、そうでないならbを返す。といった風になります。
この仕組みは、andとorの動作を、Pythonには導入されていないブーリアン演 算子のようにし、また、この機能はあなたが簡潔で魅力的な条件文を書けるよ うにします。たとえば、次の例の様にです。
if a:
print a
else:
print b
上の例の代わりに、こう書けます。
print a or b
これはPythonの慣用表現で、あなたはこれをよく使うようになるかも知れませ ん。これは、私たちがBasket.__init__メソッドの中でやったことです。引数 contentsは、デフォルトの値None(偽になる)を持っています。つまり、値を持っ ているかどうかチェックするには、こう書く事もできます。
if contents:
self.contents = contents
else:
self.contents = []
もちろん、あなたはこれよりうまい方法を既に知っていますね。では、なぜ最 初の引数にデフォルト値として[]を与えなかったかわかりますか?その理由は、 Pythonの動作の仕方に関係あります。def init(self,contents=[]):と 書いた場合、Pythonは"同一の"空リストをデフォルト値として与えます。その リストに何か詰め込まれると、このリストを使う所全てが同じ内容になってし まい、よって、デフォルト値はそれ以降、空でなくなるわけです…これについ てもっと知りたいのなら、ドキュメントを読んで"同一(identity)"と"同じ値 (equality)"の違いを調べるべきでしょう。
上でやった事を、こういうやり方でもできます。
def __init__(self, contents=[]):
self.contents = contents[:]
何をやっているのか見当はつきますか?どこででも同じ空リストを使う代わり に、contents[:]という文でコピーを作る事ができるのです。(私たちは、単純 に全体をスライスしただけです。)
これで、名前の通り"かご(Basket)"を作って使う(何かメソッドを呼び出すな ど)事ができるようになったわけです。使い方はこうなります。
b = Basket(['apple','orange'])
b.add("lemon")
b.print_me()
init__の様な魔法のメソッドは、他にもはあります。そのひとつが、 str__で、このメソッドではオブジェクトが文字列のように参照されたら、ど ういう振る舞いをするかを定義します。私たちはこれをBasketのprint_meの代 わりに使う事ができます。
def __str__(self):
result = ""
for element in self.contents:
result = result + " " + `element`
return "Contains:"+result
さあこれで、私たちがBasketインスタンスbを表示したければ、こういう風に すればいいだけです。
print b
賢いやり方でしょ?
サブクラスの作り方は、こうなります。
class SpamBasket(Basket):
# ...
Pythonは多重継承を認めているので、あなたが望むなら、コンマで区切る事で、 スーパークラスをいくつも括弧の中に入れる事ができます。クラスはx = Basket()のように継承されます。前に書いたように、コンストラクターは、__ init__という特別なメンバー関数を定義する事で作れます。SpamBasketが__ init__(self,type)というコンストラクターを持っているなら、あなたはスパ ムバスケットをy = SpamBasket("apples")のように作る事ができるという わけです。
もしあなたが、SpamBasketの中で、ひとつまたはそれ以上のスーパークラスの コンストラクターを呼ぶ必要がある場合は、Basket.init(self)のように すると呼び出す事ができます。スーパークラスの__init__は、どのインスタン スに対して呼び出されるのかという事を知らないので、selfを明確にパラメー ター中へ追加しておかないといけないという事に注意して下さい。
Pythonでのオブジェクト指向プログラミングの不思議についてもっと知りたい 方は、チュートリアル のセクション9を見て下さい。
(この章は、私が個人的にクールだと思ったから追加したわけで、Pythonにつ いて勉強するには、これを読まないといけないというわけではありません。 Python2.1での変更に関しては章末を見て下さい。)
あなたは、想像を越えた考えとかは好きな方ですか?もしそうであって、あな たが本当に大胆なら、Guido van Rossum(訳注:知っての通りPythonの創造主) のメタクラスに関 するエッセイを読んでみたいと思うかも知れません。しかし、もしあなた の脳味噌が爆発するような目に会いたく"ない"のなら、この章でお教えする、 ちょっとしたテクニックで我慢しておいた方が良いでしょう…
Pythonは字句解析ではなく動的(ダイナミック)な名前空間で実装されています。 このことは、以下のような関数を持つ事ができるということです。
def orange_juice():
return x*2
…変数(この場合はx)が、引数にも括り付けられてないし、関数の中でも与え られていません。Pythonは関数が呼ばれた場所によって、そこにある変数を使 うのです。この例の場合、こうできます。
x = 3 y = orange_juice() # y is now 6 x = 1 y = orange_juice() # y is now 2
普通、これはあなたが望んだ通りの振る舞いです(あなたは滅多に、こういう 変数へのアクセスの仕方はしないでしょうから、この例は不自然かもしれませ んが)。"しかしながら"、時には静的な名前空間があると、便利なこともあり ます。そういった理由から、関数が作られた時に、環境から値を取り込んでお くという事もできます。この動作はPythonでは、デフォルト引数によって実現 できます。
x = 4
def apple_juice(x=x):
return x*2
この例では、引数xへ、同じ名前の変数xの値が、関数が定義された時にデフォ ルト値として与えられます。よって、この関数に誰も引数を与えなければ、以 下のように動作します。
x = 3 y = apple_juice() # y is now 8 x = 1 y = apple_juice() # y is now 8
つまり、どういうことでしょう?xの値は変わらなかった訳です。もしこれが私 たちの望む動作なら、以下のように書けば良いだけでしょう。
def tomato_juice():
x = 4
return x*2
なんなら、こう書いたって差し支えありません。
def carrot_juice():
return 8
しかしながら、"重要"な事は、xの値は関数が定義された時に"環境"から取っ て来られるという事です。これは何かに使えそうじゃありませんか?実用例を 見てみましょうか?では、次は二つの関数をひとつにまとめる関数を作ってみ ましょう。
私たちは、関数がこう動くよう期待しています。
from math import sin, cos sincos = compose(sin,cos) x = sincos(3)
composeというのが私たちが作ろうという関数で、xの値は-0.836021861538に なります。これは、sin(cos(3))と同じ事です。では、これを作るには、どう したらよいでしょう?
(ここで、私たちは関数自身を引数として使っています…これ自体は、ちゃん としたテクニックです。)
明らかに、composeは二つの関数をパラメーターとして受けとらなくてはなり ません。よって、解答の骨組みは以下のようになります。
def compose(fun1, fun2):
def inner(x):
pass # ...
return inner
inner関数の中にreturn fun1(fun2(x))と書いたらいいだけじゃないのかな?と 思うかもしれませんが…それじゃあいけません。それでは、奇妙な動きをして しまいます。次の筋書きを考えてみてください。
from math import sin, cos
# Wrong version
def compose(fun1, fun2):
def inner(x):
return fun1(fun2(x))
return inner
def fun1(x):
return x + " world!"
def fun2(x):
return "Hello,"
sincos = compose(sin,cos) # Using the wrong version
x = sincos(3)
さあ、ではxには何が入っているでしょう?その通り、"Hello, world"ですね。 では、なぜそうなるのでしょう?その理由は、composeが作られた時ではなく、 呼び出された時にfun1とfun2の値を環境から取ってくるからです。これをちゃ んと動かすためには、さっき私が言ったテクニックを使えばいいのです。
def compose(fun1, fun2):
def inner(x, fun1=fun1, fun2=fun2):
return fun1(fun2(x))
return inner
これで後は、誰かがわざとこの関数を壊そうとして、ひとつ以上の引数を与え たりしないよう祈るだけです:-)。ついでに言うと、lambdaというキーワード を使う事によって、"匿名"の関数を作る事によって、実は、私たちはinnerと いう名前も必要なくなります。
def compose(f1, f2):
return lambda x, f1=f1, f2=f2: f1(f2(x))
簡潔明瞭ですね。あなたはこれが大好きになるでしょう:-)
(もしこの章の内容が理解できなくても、心配しないで下さい。少なくとも、 Pythonは"ただのスクリプト言語"以上のものだって事は、あなたに解ってもら えたと信じています:-))
Python2.1では冒険的に、静的な入れ子状のスコープ、またの呼び名を名前空 間が(オプションとして)導入されています。つまりこれは、あなたが何もトリッ キーなことをしなくても、上の章でしたのと同じ事ができるようになるという ことです。以下のように、簡単に書けばよいのです。
# This magic won't be necessary in Python 2.2:
from __future__ import nested_scopes
def compose(fun1, fun2):
def inner(x):
return fun1(fun2(x))
return inner
…これで、期待通りに動くことでしょう。
終りを前にして、あと2、3個言っておくことがあります。一番便利な関数やク ラスは、"モジュール"に入っているということです。モジュールというのは、 実際にPythonのコードが入っているテキストファイルの事です。あなたは、そ れをインポートして、自分のプログラムの中で使う事ができます。例えば、ス タンダード・モジュールのstringにあるsplitメソッドを使うには、二通りの やりかたがあります。
import string x = string.split(y)
もしくは…
from string import split x = split(y)
スタンダード・ライブラリー・モジュールに関する情報は、 www.python.org/doc/libを見て 下さい。スタンダード・ライブラリーには便利なものがたくさんあります。
全てのモジュール/スクリプトは、インポートした時に実行されます。もしあ なたのプログラムをインポート用のモジュール、単独での実行可能なプログラ ムの両方に対応させたいなら、次の様な文をコードの終りに付け加えると良い でしょう。
if __name__ == "__main__": go()
この魔法を唱えると、プログラムは実行可能なスクリプトとして動作します (つまり、このif文の中身は他のスクリプトにインポートされないという訳で す)。もちろん、go関数が直接呼び出された場合はコロンの後に続くものと同 じことをしますよ:-)
そして、UN*X上でこのスクリプトをファイル名で実行可能にしたければ、次の 文を一番最初の行に書き加えればいいでしょう。
#!/usr/bin/env python
最後に、重要な概念、"例外"について話しましょう。ある操作(何かを0で割る とか、存在しないファイルから読み込むとか)は、エラーまたは"例外"を発生 させます。あなたが自分で、適当な時に"例外"を発生させることもできます。
もし、例外に対する措置が何もされていないなら、あなたのプログラムは、エ ラーメッセージを表示して終了します。あなたはそれを、try/except文を使っ て避けることができます。例えば、
def safe_division(a,b):
try:
return a/b
except ZeroDivisionError:
return None
ZeroDivisionErrorは標準的なエラーです。この例であなたは、bが0で割れる かどうか確かめることが"できます"。しかし多くの場合、この行為は成功しな いでしょう。その上、私たちが、safe_divisionのなかでtry文を使わなかった ら、この関数を呼ぶ事は、危険極まりなくなるでしょう。私たちは、次のよう にする事もできます。
try:
unsafe_division(a,b)
except ZeroDivisionError:
print "Something was divided by zero in unsafe_division"
"普通なら"特別な問題は起こらないという場合でも、もし起こる"可能性があ る"なら、"例外"を使う事によって、代償の高くつくテストやいろいろな事を 避ける事ができることでしょう。
どうでした?これでおしまいです。あなたがこの文章で何かを学べたことを願っ てますよ。この後は、www.python.orgに 行っていろいろ試してみて下さい。そして、Pythonを学ぶ際のモットーは"ルー ク、ソースを使え!(Use the source, Luke.)"だということを、忘れないよう にして下さい(手に入れたコードを全て読め、という意味です:))。始めるに当 たって、ここに例 があります。これは、Hoareの有名な"クイックソート"アルゴリズムです。カ ラーバージョンは、 こちらにあります。
この例について、説明をひとつ付け加えておきましょう。done変数は partitionがリストの要素を走査し終ったかどうかをコントロールします。内 側のループのどちらかが、順序交換を完全に終えたという時に、doneに1がセッ トされbreak文でそこから抜け出します。では、なぜ内側のループのチェック もdoneが使われているのでしょう?その理由は、内側のループひとつ目がbreak で終了したのなら、いずれにせよ、二つ目のループが実行されるかは、メイン ループが終了しているか(doneがセットされているか)という事に依存してくる からです。つまり、doneがセットされた状況で、二つ目のループが実行された としても、doneに1をセットしてbreakするだけだからです。
while not done:
while not done:
# Iterates until a break
while not done:
# Only executed if the first didn't set "done" to 1
これと同じ、または、より明確なバージョンはこうなります。(でも、私は上 の方が好きです。)
while not done:
while 1:
# Iterates until a break
if not done:
while 1:
# Only executed if the first didn't set "done" to 1
私が、ひとつ目のループのチェックにdone変数を使っている理由は、ただ、こ の二つのループの対称性を保ちたいがためです。そういうわけで、どっちを使っ てもこのアルゴリズムは動くわけです。