携帯版は別ページ→

≪いっしょに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. Pythonプログラムの保存と読み出し

• Pythonプログラムは,拡張子を .py として保存する.上記の(2)のエディタを利用していると,ファイル名(ドットの左のファイル名の主要部)を書けば,拡張子として .py が自動で入る
• Puthonプログラムを読みだして動かすには,Run→Run Moduleとすればよい.

2. コメントの書き方

#以下は行末までコメントになる

• 半角文字の#は,使われる分野によって,ハッシュ,シャープ,ポンド,ナンバーなどと呼ばれる.
• MS-DOSの時代には,#をナンバーと読むことが多かったように思う.最近では,ツイッターでの使われ方から,ハッシュという言い方も多い.
• 留守番電話にかけていると,終了するには1のキーを,…するには「シャープ」を押してくださいというアナウンスを何度も聞かされる.コンピュータ用語の解説書には,シャープと呼ぶのは間違いであるなどと断定しているものもあるが,これほど普及したら多いものが正義になっても構わないと思う.
• Python 3.7.2のレファレンスには,ハッシュ文字(a hash characte)と書かれているので,このページでは,これによるものとする.

(1) プログラムはコンピュータが読むためのもので,コメントは人が読むために書く

• コメントとは何に使うものか,ということを端的に言えば,(1)のようになると思う.
• それなら,コンピュータが読まないものを書くのは無駄ではないのか?という素朴な疑問があり得る.これに対しては,自分が書いたプログラムでも2週間もたてば,なぜそう書いたのか分からなくなるという経験則を思い出すとよい.プログラムにエラーが見つかって,後日(数年後ということもある)訂正しなければならないときに,ある変数の働き,有効範囲などを「行間から読み解く」のは大変な作業になる.特に,それが他人の作ったプログラムであるような場合に,暗黙の前提となっていることが分かりにくい.こうした分かりにくさを避けて,メンテ作業を行う場合に備えて,重要な箇所にはコメントを書いておく方がよい.

(2) 1つの行で#が書かれた箇所からその行の右端まではコメントとなり,プログラムとしては使われない

• #によるコメントアウト(コメントとしてプログラムから外すこと)を行う場合は,各行ごとに行う必要があり,複数行をまとめてコメント行にすることはできない.
• #といっても,シングルクォートやダブルクォートで囲まれた文字列の中にあるハッシュ文字(#)は,単なる文字として扱われる.
• 一度#が登場したら,その行の行末までに何個の#があっても,効果は同じだから,長いプログラムの区切りとして,#自体を目印の絵文字として使うことも可能.例えば,
### ---------------作業1 ここから strat ---------------- ###
… …
### ---------------作業1 ここまで end ------------------ ###

(3) 実際に動くプログラムの配布用に#を付けておく使い方も考えられる

• 32ビット機か,64ビット機か,Windows 10か,それ以前か,Macか,Androidかなど,ユーザの利用環境によって異なるプログラムになるとき,行の先頭に#を付けておき,ユーザ自身が自分の利用環境に合う行のコメントマーク(#)をはずすという使い方がある.
• 初心者向けに,とりあえず確実に動くプログラムを配布して,行頭の#を1つずつ消して,プログラムを動かしてみる中で,体験から学ぶようにすると講義・演習はどんどん進める.

3. 文(命令文,ステートメント,コマンド)の書き方

(1) Pythonの文(ステートメント)は行の左端から書く

• Pythonでは,1行の文は行の左端に詰めて書く.
• C言語やJavascriptの場合のような,文の末を表すセミコロン(;)は要らない.
【例 3.1.1】
_print('a')
→ 行の左端にスペースが1つあるからエラーになる
【例 3.1.2】
print('a')
→ これで実行すると a が画面に表示される.シングルクォートは付かない.
→ 文の後に無駄なスペースがあるのは,構わない

(2) インデント(字下げ)によって文の構造を表す

• Pythonで複文のブロックを書くとき,C言語やJavascriptの場合のような,波かっこ{ }は使わずに,インデントの深さによって表す.
• Pythonのエディタで書くと,コロン(:)の後に必要なインデントは自動的に入る.
• 外部のテキストエディタでPythonのソースファイルを書いた場合,インデントをタブキーで表すこともできるが,Pythonの参考書などでは,インデントはスペース4個と決める方がよいとされている.実際,Pythonのエディタで書くと,1段目のインデントはスペース4個,2段目のインデントはスペース8個,…になる.
【例 3.2.1】 ≪Javascriptで書いた場合≫
//1けたの奇数の和を求めるプログラム
var sum1 = 0;
for( kk = 1; kk < 10; kk++)
{if(kk % 2 == 1)
  sum1 += kk;
}
document.write(sum1);
≪Pythonで書いた場合≫
sum1 = 0
for kk in range(1,10):
  if kk % 2 == 1:
    sum1 += kk
print(sum1)

4. if, elif, elseによる分岐

(1) if, elseで2つに場合分けする

【例 4.1.1】
//絶対値にするプログラム
k1 = 3
if k1 < 0:
  print(-k1)
else:
  print(k1)
→ 3
• if分岐を入れ子にすることもできる
【例 4.1.2】  |x(x-2|を求める
x = 1
if x < 0:
  print(x*(x-2))
else:
  if x < 2:
    print(-x*(x-2))
  else:
    print(x*(x-2))
→ 1
(赤で示したifとelseのインデント(字下げ)がそろっていないとエラーになる)

(2) if, elif, elseで3つ以上に場合分けする

• 他のプログラミング言語で,elseif, else ifなどと書くものをPythonでは短くelifと書く
【例 4.2.1】
w_list = ['Sun','Mon','Tue','Wed','Thu','Fri','Sat']
s_list = ['spring','summer','autumn','winter']
str1 = 'March'
if str1 in w_list:
  print('week day')
elif str1 in s_list:
  print('season')
else:
  print('other')
→ other

• ネスト(入れ子)の深い分岐(A)よりも,elifの繰り返しでウナギの寝床のような形にする(B)と見やすく=間違いにくくなる.
• 最も不公平なトーナメント(B)を目指す.
【例 4.2.2】 (A)ネストの深い分岐
hand1 = ['ぐ','ち','ぱ']
a = 'ち'
b = 'ぱ'
if a == hand1[0]:
  if b == hand1[0]:
    print('あいこ')
  else:
    if b == hand1[1]:
      print('a')
    else:
      print('b')
else:
  if a == hand1[1]:
    if b == hand1[0]:
      print('b')
    else:
      if b == hand1[1]:
        print('あいこ')
      else:
        print('a')
  else:
    if b == hand1[0]:
      print('b')
    else:
      if b == hand1[1]:
        print('a')
      else:
        print('あいこ')
→ a
【例 4.2.3】 (B)最も不公平なトーナメント
hand1 = ['ぐ','ち','ぱ']
a = 'ち'
b = 'ぱ'
if a == hand1[0] and b == hand1[0]:
  print('あいこ')
elif a == hand1[0] and b== hand1[1]:
  print('a')
elif a == hand1[0] and b== hand1[2]:
  print('b')
elif a == hand1[1] and b== hand1[0]:
  print('b')
elif a == hand1[1] and b== hand1[1]:
  print('あいこ')
elif a == hand1[1] and b== hand1[2]:
  print('a')
elif a == hand1[2] and b== hand1[0]:
  print('a')
elif a == hand1[2] and b== hand1[1]:
  print('b')
else:
  print('あいこ')
→ a

5. forを用いたイテレーション(反復処理,ループ)

(1) for 変数 in range(): … range()を使ったイテレーション

【書式】
range(start=0, stop, step=1)
• 第1引数startが省略された場合,デフォルト(既定値)の0が使われます.
• 第2引数stopは省略できません.stopに指定された値の前まで使われるので,startが0のとき,正の整数stopは繰り返しの回数に対応します.
• 第3引数stepが省略された場合,デフォルト(既定値)の1が使われ,1ずつ増えます. • start, stop, stepのいずれも整数でなければなりません.0.1〜0.9まで0.1ずつ増加するような数列は,range()オブジェクトでは書けません.
引数nが1個の場合,start=0が省略されて,stop=nと書かれているものと解されます.
【例】 range(5) → 0,1,2,3,4
引数がm,nの2個の場合,start,stopの順に書かれているものと解されます.
【例】 range(1,5) → 1,2,3,4
引数がm,n,sの3個の場合,start,stop,stepの順に書かれているものと解されます.
【例】 range(3,10,2) → 3,5,7,9
stepが負の数という指定も可能です.
【例】 range(5,0,-1) → 5,4,3,2,1
step>0のときstart, start+sep, start+2*step, ...<stopに該当する数がなければ,このrange()オブジェクトは空になります
【例】 range(2, 1) → 空になる
【例 5.1.1】
≪for 変数1 in range()により,range()にある値が順に変数1に渡される≫
sum1 = 0
for kk in range(1,11,1):
  sum1 += kk
print(sum1)
→ 55
変数sum1は0に初期化
1,2,3,...,10まで増加させる
順に和に加える
ループを抜け出たら,和を表示
1+2+3+...+10=55になる

(2) for 要素 in リスト:…リストの要素を順にたどるイテレーション

【書式】
for 要素 in リスト:
繰り返す処理
• リストの要素を順に調べて,処理を行う.
【例 5.2.1】
≪for 変数 in リスト:により,リストの要素が順に変数に渡される≫
L1 = ['spring','summer','autumn','winter']
for str1 in L1:
  print(str1, end=' ')
→ spring summer autumn winter

(3) for 要素 in タプル:…タプルの要素を順にたどるイテレーション

【書式】
for 要素 in タプル:
繰り返す処理
• タプルの要素を順に調べて,処理を行う.
【例 5.3.1】
tp1 = 'sun','mon','tue','wed','thu','fri','sat'
(かっこ( )を省略しても,カンマ区切りの列はタプルの定義と見なされる)
for str1 in tp1:
  print(str1.title(), end=' ')
(文字列.title()は,単語ごとに先頭を大文字,他を小文字にする)
→ Sun Mon Tue Wed Thu Fri Sat

(4) for 要素 in 辞書:…辞書のキーを順にたどるイテレーション

【例 5.4.1】
≪単にin 辞書とすれば,辞書のキーと照合する≫
dic1 = {'お':'大阪','き':'京都','こ':'神戸'}
for city1 in dic1: (for city1 in dic1.keys():と同じ)
  print(dic1[city1], end=' ')
→ 大阪 京都 神戸
(city1が,キーの'お'であるとき,dic1[キー]は対応する値の'大阪になる')
【例 5.4.2】
≪辞書の値と照合するには,辞書.values()とする≫
dic1 = {'お':'大阪','き':'京都','こ':'神戸','キ':'京都'}
for city1 in dic1.values():
  print(city1, end=' ')
→ 大阪 京都 神戸 京都
(辞書には同一のキーは存在できないが,同一の値は存在できる.この例では,city1が辞書の値になる)

(5) for 要素 in 集合:…集合の要素をたどるイテレーション

【例 5.4.1】
≪集合の要素は並び方が決まっていないが,各要素を1回ずつたどることはできる≫
set1 = {'Osaka','Kyoto','Kobe'}
for c1 in set1:
  print(c1, end=' ')
→ Kyoto Osaka Kobe
(入力したときの並び方と異なる順に登場している)

6. whileループ

(1) whileの基本

【重要】
 whileループを練習する前に,プログラムが暴走したときに,止める方法を身に着けておく方がよいでしょう.
 forループと違って,whileループはわずかな書き間違いで,無限ループになってしまうことがありますので,この止め方を覚えておくことは重要です.
暴走したら,Ctrl+cで止める
(キーボードの左下にある「Ctrl」キーを押しながら,「c」を押す)
• forループが,初めと終わりによって「回数」を決めて繰り返し処理を行うのに対して,whileループは「条件」を指定して繰り返し処理を行います.
• whileループは,繰り返す回数を前もって予想できない場合にも使えます.
• whileループを使うときは,無限ループにならないように気を付けなければいけません.
【書式】
while 継続条件:
繰り返す処理
または
while ( 継続条件 ):
繰り返す処理
複数個の処理を繰り返すときは,インデント(字下げ)幅がそろわなければなりません.
while ( 継続条件 ):
繰り返す処理1
繰り返す処理2
【例 6.1.1】
(米つきバッタのように,代わりに謝ってくれるプログラムです)
count1 = 1
while count1 <= 5:
  print('すみません')
  count1 += 1

すみません
すみません
すみません
すみません
すみません
…(1)
…(2)
…(3)
…(4)

 初めに(1)で変数count1の値を1に初期化しておく.
 (2)でこのループを継続するかどうかを count1 <= 5 の真偽によって判定する.1 <= 5はTrueだから,ループは継続される.
 仮に,(1)でcount1 = 6などとなっていれば,この継続条件は一度もに満たされないから,このループ内の処理は一度も実行されずにループは終わることになる.
 count1が1で継続条件を満たした場合は,'すみません'を印字して改行する.
 次に,count1 += 1により,count1は2になる.
 whileの継続条件 count1 < 5を満たしているかどうかを判定する.2 < 5だから,'すみません'を印字して改行する.
 この処理は,count1が5になるまで繰り返される.
 そして,count1 += 1により,count1が6になったら,whileの継続条件 count1 <=5 を満たさなくなるから,ループを抜け出る.
 仮に,(4)式が書かれていなかったら,どこまで行っても count1 <= 5が成り立つから,無限ループとなって,コンピュータが暴走する.【重要】という所で書いたように,暴走したらCtrl+cで強制的に止めるしかない.

(2) ループの中でのbreak, continue, elseの働き

【書式】
while 継続条件A: …(1)
if 条件B:
繰り返す処理1
break
else:
繰り返す処理2
continue
else:
繰り返す処理3
…(2)
• whileループの中でbreak文に出遭うと,以下の処理を打ち切って,ループの外(2)に抜け出る.
• continue文に出遭うと,以下の処理を行わずに(1)に戻る.
• ifに対応するelseとwhileに対応するelseは,インデントの深さによって区別される

【書式】
for 継続条件A: …(1)
if 条件B:
繰り返す処理1
break
else:
繰り返す処理2
continue
else:
繰り返す処理3
…(2)
• forループの中でbreak文に出遭うと,以下の処理を打ち切って,ループの外(2)に抜け出る.
• continue文に出遭うと,以下の処理を行わずに(1)に戻る.
• ifに対応するelseとforに対応するelseは,インデントの深さによって区別される

【例 6.2.1】
count1 = 1
while count1 <= 3:
  pwd =input('4けたの暗証番号を入力してください>')
  if pwd == '9999':
    print('ようこそ')
    break
  else: #1
    print('違います')
    count1 += 1
    continue
else: #2
  print('3回連続で間違いました')
  print('しばらく後に再試行してください')
• このプログラムは,あらかじめ定めた暗証番号(上記では仮に9999としてある)に対して,入力した番号が一致したら,「ようこそ」と表示して,次の処理に入れるようにしたものです.
• 間違ったら,#1のelse:に制御の流れが移り,「違います」と表示され,カウンター(count1)が1増加して,while条件の判定に戻ります.
• 3回連続で間違った場合=break文によってでなく,while条件によって正常終了した場合,#2のelse:に制御の流れが移ります.
• forまたはwhileループの中でbreak文に出遭うと,以下の処理を打ち切って,ループの外に抜け出る.
• forやwhileのループがネスト(二重以上の入れ子)になっているとき,1つのbreakによって抜け出るのは,一番内側のループだけ.もし,外側のループも抜け出られるようにしたければ,外側のループで判別できる変数の値を変えるなどの工夫が必要になる.
【例 6.2.2】
(次のプログラムでは,k1が1から6まで増加するときに,各々のk1に対してn1も1から6まで増加する.n1>k1となったときに,それらの数字を印字してから#1のbreakでループを抜け出るつもりであるが,#1のbreakによって,#2のendには行かず,外側のループに出るだけなので,印字は何度も行われる)
for k1 in range(1,7):
  for n1 in range(1,7):
    if n1 > k1:
      print(k1,n1)
      break #1
    else:
      continue
print('end') #2

1 2
2 3
3 4
4 5
5 6
end
【例 6.2.3】
(次のプログラムでは,外側のループを出るための目印の変数mark1(#1)を設定し,mark1が2になったら(#3)出られるように(#4)してある.内側のbreak(#9)によって,制御の流れは#2に行くだけで,#12には行かない)
mark1 = 1
for k1 in range(1,7):
  if mark1 == 2:
    break
  for n1 in range(1,7):
    if n1 > k1:
      print(k1,n1)
      mark1 = 2
      break
    else:
      continue
print('end')
#1
#2
#3
#4
#5
#6
#7
#8
#9
#10
#11
#12


1 2
end
• continue文に出遭うと,以下の処理を行わずにループの更新条件の判定に戻る.
【例 6.2.4】
(次のプログラムは,カウンター(count1)の値をインクリメント(増加)させずにcontinue文を書いているので,プログラマの意図に反して,何回でも間違えることができる.すなわち,何回間違えてもwhile条件は成立する)
count1 = 1
while count1 <= 3:
  pwd =input('4けたの暗証番号を入力してください>')
  if pwd == '9999':
    print('ようこそ')
    break
  else: #1
    print('違います')
    continue
  else: #2
    print('3回連続で間違いました')
    print('しばらく後に再試行してください')
• break, continueの働きはC言語やJavascriptと同様であるが,Pythonにはwhileまたはforに対するelseがある点が異なる.ifに対応するelseか,for, whileに対応するelseであるかは,インデント位置がifと並んでいるかfor, whileと並んでいるかによって判断できる.
【例 6.2.5】
(次のプログラムは,elseのインデントがwhileに対応していないから,エラーになる)
count1 = 1
while count1 <= 3:
  pwd =input('4けたの暗証番号を入力してください>')
  if pwd == '9999':
    print('ようこそ')
    break
  else: #1
    print('違います')
    count1 += 1
    continue
  else: #2
    print('3回連続で間違いました')
    print('しばらく後に再試行してください')
• break文によってでなく,while条件の不成立によって正常終了した場合,whileに対応するelse:に制御の流れが移ります.
 すなわち,breakによる異常終了の場合は,while対応のelseに制御は移らない.
【例 6.2.6】
str1 = '0'
while str1 != '4':
  str1 = input('番号は?>')
  if str1 == '2':
    print('A地点')
    continue
  elif str1 == '3':
    print('B地点')
    break
  else:
    print('C地点')
    continue
else:
  print('D地点')
#1
#2
#3
#4
#5
#6
#7
#8
#9
#10
#11
#12
#13
#14
#15


0 → C地点
1 → C地点
2 → A地点
3 → B地点
4 → C地点 D地点

#10→#11→#12で#2に戻る
#10→#11→#12で#2に戻る
#4→#5→#6で#2に戻る
#7→#8→#9でループを出て#15
#10→#11→#12で#2に戻り
条件不成立で#13→#14→#15

• if, elif, elseで以下の処理を打ち切るためにbreakやcontinueを使うことはできない.break, continueはループに対してだけ働く.
【例 6.2.7】
(次のプログラムは,ループの中でない箇所にbreakが使われているから,エラーになる)
#暗証番号は314とする
num1 = input('1桁目の番号は?>')
if num1 == 3:
  num2 = input('2桁目の番号は?>')
  if num2 == 1:
    num3 = input('3桁目の番号は?>')
    if num3 == 4:
      print('お入りください')
      break
    else:
      print('3桁目が違います')
      break
  else:
    print('2桁目が違います')
    break
else:
  print('1桁目が違います')

7. pass文

• pass文は何もしないことを表す.
• 実用的なプログラムで使われることは少ないと考えられるが,その場所に何かを書かなければ文法的にエラーとなるような場合に,passと書く.
if文, for文, 関数定義などにおいて,空のブロックのまま放置するとエラーになる場合
【例 8.1】
if 1 == 2:
pass
for nn in range(5):
pass
def func1():
pass

8. zip()関数

• zip()関数は,多重ループを作るものではなく,行ベクトルから列ベクトルを作るようなものです.
• 図のように要素数が各々5個,3個,4個の3つのリストがあるとき,zip()関数を使えば,1列目,2列目,3列目から成るリストが作れます.
• 要素数の最も少ない値までで打ち切るので,長い方のリストの末尾は使われません.
【例 8.1】
row1 = [1, 4, -5, 3]
row2 = [-2, 0, -1, 2, 7]
row3 = [-3, 2, 6]
for r1,r2,r3 in zip(row1,row2,row3):
  print(r1,r2,r3)

1 -2 -3
4 0 2
-5 -1 6
(すべての組合せができるのではなく,1列目の組,2列目の組,3列目の組ができます)
zip()を使った上記のプログラムは,列の最小値min(len(row1), len(row2), len(row3))とrange()を使う次のプログラムと同じです
【例 8.2】
row1 = [1, 4, -5, 3]
row2 = [-2, 0, -1, 2, 7]
row3 = [-3, 2, 6]
col_min = min(len(row1), len(row2), len(row3))
for n in range(col_min):
  print(row1[n], row2[n], row3[n])

1 -2 -3
4 0 2
-5 -1 6
【例 8.3】
子どもが好きなものがジャンル別に並べてあるときに,年代別に並べなおすと
row1 = ['巨人','広島','阪神','川崎F','川崎F']
row2 = ['大鵬','イチロー','大谷']
row3 = ['卵焼き','ラーメン','ハンバーグ','カレー']
for team1, hero1, food1 in zip(row1,row2,row3):
  print(team1, hero1, food1)

巨人 大鵬 卵焼き
広島 イチロー ラーメン
阪神 大谷 ハンバーグ
(チーム名,ヒーロー,食べ物の順に3組までできる)
○== メニューに戻る ==