←PC版は別ページ

≪いっしょにPython≫ プログラマーの実験ノート

 このページは,プログラム言語Pythonをこれから学ぼうと考えている筆者の備忘録です.
 そこそこ調べて書いていますが,仕様を精密に調べたものではありません.どちらかと言えば,実装されたPython 3を使ってみてどうなったかということを中心に書いたものです.いわば,実験ノートの記録です.
Pythonの練習には,
(1) IDLEというメニューから入って,>>>というプロンプトが表示される状態で使う場合
• 画面の上端がPython 3.7.x Shellとなっていて,2行目がFile, Edit, Shell, Debug, ...となっている
• 1行入力するたびに,エラーを確かめながら処理を進める,対話型インタプリタの形になっている
(2) IDLEというメニューから入って,左上端のFileをクリック→New Fileと進む場合
• 画面の上端がファイル名(初めはUntitled)となっていて,2行目がFile, Edit, format, Run, ...となっている
(3) Python 3.7.x という真っ黒なコマンドプロンプトの画面(ターミナルウィンドウ)から入るもの
の3通りが使えるが,以下は(2)のNew Fileから,テキストエディタを使って,プログラムを書く場合を考える.

1. クラスとオブジェクト

(1) プロパティとメソッドを持つオブジェクトの例

難しい理屈を読む前に,とりあえず動く簡単な例を見ておく
【用語】
オブジェクト…「クラスのインスタンスがオブジェクトだ」と言われることが多いが,ここではとりあえず,クラスの設計図に沿って作られるものがオブジェクトで,実際に使われている個別のオブジェクトをインスタンス(instance,実例)と呼ぶことにして,話を始めたい.
論者によって,あるいは文脈によっては,オブジェクトという用語は,クラス側に引き寄せて使われる場合も,インスタンス側に引き寄せて使われる場合もあるが,クラスとインスタンスという用語の使われ方には曖昧さがない.
プロパティ…オブジェクトの中に定義されている変数,データ(値をもっている)
メソッド…オブジェクトの中に定義されていてプロパティを操作できる関数
【使い方】
プロパティ… インスタンス名.プロパティ名
メソッド…インスタンス名.メソッド名()
【例 1.1.1】
【Javascriptのオブジェクト定義と使用法の例】
≪オブジェクト定義の部分≫
Javascriptでは,functionを使ってオブジェクトを定義し,プロパティとメソッドを表すときにオブジェクト自身を表すためにキーワードthisを使う.
function img1(w1, h1, str1)
{this.width = w1;
this.height = h1;
this.name = str1;
this.area = function compute_area()
{return this.width * this.height;
}
}
≪オブジェクト呼び出しの部分≫
Javascriptでは,オブジェクトのインスタンスを生成するにはnew演算子を使う.
pic1 = new img1(3,5,'rect');
sqr1 = new img1(5,5,'square');
≪プロパティとメソッドを利用するには,ドット(.)でつなぐ≫
document.write(pic1.width+',');
document.write(pic1.name+',');
メソッドの定義式には括弧を付けず,実行文には括弧を付ける
document.write(sqr1.area()+',');
≪実行結果≫
→ 3,rect,25,
【Pythonのオブジェクト定義と使用法の例】
Pythonでは,classを使ってオブジェクトを定義し,プロパティとメソッドを表すときにオブジェクト自身を表すためにキーワードselfを使う.
class img1: # この行には引数を書かない.後に述べる既存クラスの継承を書くときに使う.
def __init__(self, w1, h1, str1): # 初期化関数の第2引数から後をユーザが決める
self.width = w1
self.height = h1
self.name = str1
def area(self):
return self.width * self.height
≪オブジェクト呼び出しの部分≫
pic1 = img1(3,5,'rect') # Pythonでインスタンスの作成するとき,new演算子は不要.第2引数から後を引数にする
sqr1 = img1(5,5,'square') # 第2引数から後を引数にする
≪プロパティとメソッドを利用するには,ドット(.)でつなぐ≫
print(pic1.width)
print(pic1.name)
print(sqr1.area())
≪実行結果≫

3
rect
25

【少しずつ確かめよう】
• Pythonのオブジェクトはキーワードclass クラス名:の形で定義する.
class クラス名:
class クラス名(): のように括弧を付けてもよいが,付けなくてもよい.
 この括弧は,既存クラスを継承するために使い,何も書かれなければobject型を継承したものと見なされる.
 括弧を付けるとき,括弧の中に書き込むのは,定義済みの他のクラスを継承する場合で,いわゆる引数はここには書かず,下の__init__()の第2引数以下に書く.
• 他方で,引数のないクラスを定義した場合でも,インスタンスを作成するには,
インスタンス名 = クラス名()
 の形で,クラス名に括弧を付ける.
【例 1.1.2】
#クラスの定義
class hello1: # 括弧はなくてもよい.その場合,object型になる.
def __init__(self):
self.talk = 'ハロー'
#インスタンスの作成
to_you = hello1() #括弧が必要.なければエラーになる.
#インスタンスのプロパティを表示
print(to_you.talk)
【例 1.1.2の補足説明】
#クラスの定義
class hello1(): # 括弧はあってもよい.空欄だからobject型になる
def __init__(self):
self.talk = 'ハロー'
#インスタンスの作成
to_you = hello1 #クラス名に括弧がなければエラーになる.
to_you() = hello1() #インスタンス名に括弧があるのはエラーになる.

【少しずつ確かめよう】
• オブジェクトを定義するときは,前後にアンダースコアを2つずつ書く特別な初期化メソッド__init__()を書き,オブジェクト自身を表すための仮引数のselfを第1引数として書く.
 __init__()があれば,オブジェクトが作られたら自動的に呼び出される.プロパティの初期設定などに使うには,この名前を使う.
def __init__(self):
 ※アンダースコアで始まる変数名(プロパティ)や関数名(メソッド)は,システムが特別な使い方をすることがあるので,各々のユーザが使うのは避けた方がよい.
• プロパティを使わず,他に難しい使い方をしない場合,__init__()を書かなくてもクラスの定義はできる.
• オブジェクトに引数を持たせるときは,__init__()メソッドの第2引数以下に書き並べる.
 正確に言えば,仮引数のselfという名前は,変更可能とされているが,ほとんどの解説書でこの記号が使われているので,読む人が分かり易いように習慣に従ってselfのまま使う方がよい.
def __init__(self, 引数1, 引数2,...):
• このメソッド__init__()の戻り値を使うことは想定されておらず,None以外の戻り値を設定すると,エラーになる.
【例 1.1.3】
#クラスの定義
class area1:
def __init__(self, w1, h1):
self.width = w1#プロパティの名widthは仮引数w1と違ってもよい
self.height = h1#プロパティの名heightは仮引数h1と違ってもよい
#インスタンスの作成
s1 = area1(3, 4)
#インスタンスのプロパティを表示
print(s1.width)
→ 3

【少しずつ確かめよう】
• クラスのメソッド(関数)では,引数selfを必ずつける.これにより,プロパティが操作できるようになる.
def func1(self):
• クラスのメソッドでself以外の引数を使うときは,第2引数以下に並べる.
def func1(self, x1, y1):
【例 1.1.4】
class area1:
def __init__(self,w1,h1):
self.width = w1
self.height = h1
self.calk() #ここにメソッドを書いておくこともできる.その定義は下に書く.
#ここに書いておくと,プロパティとメソッドの一覧が見やすくなる
def calk(self):
return self.width * self.height
s1 = area1(3,4)
print(s1.calk())
→ 12
【1.1 ここまでのまとめ】
class クラス名: #または class クラス名():
#class クラス名()の括弧には,いわゆる引数は書かない.この括弧は既存クラスを継承するときに使う
def __init__(self,仮引数1,仮引数2): #この名前にしておくと自動的に呼び出されて初期化が行われる
self.プロパティ名1 = 仮引数1 #仮引数名とプロパティ名は同じでなくてもよい
self.プロパティ名2 = 仮引数2
self.メソッド名() #ここにメソッドも書いておくと,プロパティとメソッドの一覧が見やすくなる
def メソッド名(self):
処理
インスタンス名 = クラス名(実引数1,実引数2) #インスタンスの作成.Pythonではnew演算子は不要.
#左辺のインスタンスには括弧は付けない.右辺のクラス名には,最初の定義に括弧を付けていなくても,括弧を付ける.

#プロパティを読み出すには
インスタンス名.プロパティ名
#メソッドを読み出すには
インスタンス名.メソッド名()

(2) プロパティの書き換え,追加,削除

• クラスの設計図に従ってインスタンスを生成した後,そのインスタンスについてだけ,プロパティを書き換え,追加,削除するには
【プロパティの書き換え】
インスタンス名.プロパティ名 = 値 #コマンドラインで単に代入すればよい
【プロパティの追加】
インスタンス名.新プロパティ名 = 値 #コマンドラインで新プロパティ名を書いて,単に代入すればよい
【プロパティの追加】
del インスタンス名.プロパティ名 #コマンドラインでdel演算子を付ける
≪例≫
元のインスタンスinst1のプロパティが
inst1.x == 3, inst1.y == 4 のとき
inst1.x = 5 により
inst1.x == 5, inst1.y == 4 になる
さらに,inst1.z = 7 とすると
inst1.x == 5, inst1.y == 4, inst1.z == 7 になる
さらに,del inst1.x とすると
inst1.y == 4, inst1.z == 7 になる
【例 1.2.1】
class word1:
def __init__(self,s1,s2):
self.str1 = s1
self.str2 = s2
w1 = word1('blue','bird')
print(vars(w1)) #関数vars()はオブジェクトのプロパティを名前:値の辞書として表示します
→ {'str1': 'blue', 'str2': 'bird'}
w1.str1 = 'red'
print(vars(w1))
→ {'str1': 'red', 'str2': 'bird'}
w1.str3 = 'many'
print(vars(w1))
→ {'str1': 'red', 'str2': 'bird', 'str3': 'many'}
del w1.str1
print(vars(w1))
→ {'str2': 'bird', 'str3': 'many'}

(3) クラスの継承

• class クラス名2(クラス名1):の書式で既存のクラス1の持つすべてのプロパティとメソッドがクラス2でそのまま使える.
• この場合,既存のクラス1を親クラス(スーパークラス,基底クラス),新しく作ったクラス2を子クラス(サブクラス,派生クラス)と呼ぶ.
【例 1.3.1】
• animal1クラスのように親クラスが省略されているときは,システムの側で定義されているビルドイン・オブジェクトのobject型が親クラスと見なされる.
• 子クラスdog1のインスタンスd1は,何も定義しなくても(pass),親クラスanimal1のプロパティvoiceとメソッドvoice1()が使える.

(4) メソッドのオーバーライド(上書き)

• 通常,オーバーライドは上書きと訳されるが,対応する英語はoverwriteではなく,override(覆す,踏み潰す)になっている.実際には,ファイルの上書きと同様に,後から書いた方が生き残って,前に書かれていた方は残らないから,意味としては同じになる.[先客有利ではなく,後出しジャンケンの勝ち]
• クラスを継承した方の子クラスで,親クラスと同じ名前のメソッドを作成すると,子クラスでは上書きされた方のメソッドが生きる.
• メソッドがオーバーライドされているときに,親クラスの同一名のメソッドを呼び出すには,super()を付ける.
【例 1.4.1】


きゃん
わん
• 1代目→2代目→3代目のように2段階の継承が行われているとき,3代目から見たsuper()は2代目になる
• オーバーライドされているときに,3代目が1代目のメソッドを使うには,クラス定義では次の(*1),コマンドラインからは(*2)のように書く
【例 1.4.2】

わん3
わん2
わん1

(5) 多重継承の場合

• 次の例のように第3のクラスが2つのクラスを継承している場合,継承リストの先に書かれているdog1のメソッドが優先的に使われる
【例 1.4.3】
→わん1
○== メニューに戻る ==