ノート: instant python
前回のinstant hackingに引き続き、instant pythonも読みました。その際のノートです。
なお途中の「Objects and Stuff…」までです。「A Jedi Mind Trick」以降はまた次回。
The basics
インデントでブロックを表現するよとか、データ構造とか、基本的なこと。割愛。
Functions
関数について。
- 引数は値渡し
- ローカル変数のスコープの話など。関数内のローカル変数の値を変更しても、関数の外には影響しない。まあ直感的ですね
- 関数を変数に入れたりできる(関数オブジェクト?)。関数型言語っぽい。
def square(x): return x*x queeble = square print queeble(2) # Prints out 4
Objects and Stuff…
クラスとオブジェクトについて。
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
- すべてのメソッドの最初の引数に、オブジェクト自身をあらわすselfをいれる
- メソッドはこんな風につかう:object.method(arg1,arg2)
- __init__というメソッドはコンストラクタ
- 引数にデフォルト値を与えることもできる。(上の例だとコンストラクタの引数contents)
- short-circuit logic。詳しくは後述
- バッククオート(`)でオブジェクトを囲うと、文字列表現になる
- 「+」演算子はリストや文字列に対して使える
short-circuit logicについて
pythonでは、[]、0、""などの「空要素」は「偽」、その他の要素([0]、1、"hello world"など)は「真」になる。ここで、たとえば「a and b」という表現は、次のように評価される:
- aの真偽をチェック
- 偽なら、aを返す
- 真なら、bを返す
逆に、「a or b」ならば、次のように評価される:
- aの真偽をチェック
- 真なら、aを返す
- 偽なら、bを返す
たとえば、「print a or b」をif-elseで実現すると、次のようになる:
if a: print a else: print b
これが「short-circuit logic」
ここで上記の例を考えてみる。コンストラクタ__init__の引数contentsに、値が渡されたかどうかで動作が変わる。short-circuitではなく、else-ifで再現した場合、
if contents: self.contents = contents else: self.contents = []
となる。ここで、contentsのデフォルト値を[]にすれば、こんな面倒な処理をしなくてよい気がするが、わざわざこのように実装しているのはなぜだろうか。python処理系は、デフォルトの値として、別のBasketクラスのインスタンスにも、全く同じ空リストを渡してしまう。つまり、インスタンスAのリストの内容を変更したとすると、その後に作ったインスタンスBのcontentsの中身も変化してしまう。よってこのような実装になっている。このへんのことは、ドキュメントで、 identityとequalityの違いについて調べると良い。
また、こういう実現法もある。
def __init__(self, contents=[]): self.contents = contents[:]
[:]は単に全要素をコピーしている。
クラスの利用
b = Basket([‘apple’,’orange’]) b.add(“lemon”) b.print_me()
ふつうですね。
__str___
__str__は、インスタンスが文字列のように扱われたときの動作を定義する。たとえば、
def __str__(self): result = “” for element in self.contents: result = result + ” ” + `element` return “Contains:”+result
と定義しておき、
print b
とすることで、最初の例のprint_me()メソッドと同様の動きをする。
継承
Basketクラスの子クラスSpamBasketを作るには、こうする:
class SpamBasket(Basket): # …
pythonでは多重継承(複数の親クラスを持つこと)ができる。その際は、括弧のなかでコンマ区切りで親クラスを列挙する。
コンストラクタの中から、親クラスのコンストラクタを呼ぶことができる。たとえば、SpamBasketのコンストラクタの中から、Basketのコンストラクタを呼ぶには、
Basket.__init__(self)
とする。
pythonでのオブジェクト指向プログラミングについては、チュートリアルの9章を参考にすると良い。
続く…