#!/usr/bin/env python # coding: utf-8 # # とりあえずPython interactive shellを使ってみる # ## まずは四則演算など # In[1]: 1 + 2 # In[2]: 1 - 2 # In[3]: 7 * 3 # In[4]: 7 / 3 # ここまでで,少なくとも電卓の代わりになりそうだとわかる. # # # 四則演算ほど基本的ではないが,べき乗,商,余りなどの演算子も用意されている. # In[5]: 2 ** 3 # 2の3乗は8 # In[6]: 7 // 3 # 7を3で割った商は2 # In[7]: 7 % 3 # 7を3で割った余りは1 # 見て分かる通り,Pythonでは,#以降行末まではコメントとして扱われる. # # 演算の優先順位を括弧()で指定できる. # In[8]: (3 - 7 / 4) * 8 # In[9]: 3 - 7 / 4 * 8 # ## 変数の利用 # 一度の命令では複雑な計算はやりづらい. # 変数を利用すると,前の計算結果をつぎつぎと利用して,複雑な計算をできる. # In[10]: x = 3 # In[11]: x # In[12]: y = x + 4 # In[13]: y # Pythonでは,他の多くのプログラミング言語と同様に,=の右辺を=の左辺に代入する. # (正確に言うと代入ではなく名前の付替えなのだが,それはいずれ説明する.) # 左辺には変数を,右辺には式を書く. # 少なくとも1度代入された変数を単独で呼ぶと,その値が出力される. # Pythonのキーワード(今後紹介するfor,ifなど)以外の文字の列は,新たな変数とみなされる. # すなわち,Pythonでは変数宣言は必要ない. # In[14]: z # ただし,一度も代入されていない文字の列は,未定義な何かとみなされてエラーとなる. # In[15]: z = x * y # In[16]: z # In[17]: miya = 'yuichiro' # In[18]: miya # Pythonで,値としての文字列を扱いたい場合には,シングルクォーテーションで囲む. # あるいはダブルクオーテーションで囲む. # In[19]: japan = "nippon" # In[20]: japan # 文字列の中にシングルクォーテーションそのものを入れたい場合にはダブルクオーテーションを使うのが良い. # In[21]: tonight = "kon'ya" # In[22]: tonight # ## リストの利用 # 複数データを扱うためのPythonにおける最も基本的な構造はリストである. # 例えば,数字の列3, 1, 4を変数xに代入したければ以下のようにする. # In[23]: x = [3, 1, 4] # In[24]: x # リストの要素には数字だけでなく,文字列やその他のもの,例えばリストそのものも使える. # また,1つのリストの中で要素の種類が異なっていても問題ない. # In[25]: x = [3.14, 'abc', 8, [1, 2, 3]] # In[26]: x # リストの要素には,添字の指定でアクセスできる. # Pythonのリストの添字は,C言語やJavaと同様に,0始まりである. # In[27]: x[1] # In[28]: x[3][0] # 添字を指定して代入すれば,リストそのものを部分的に書き換えられる. # In[29]: x[2] = 'de' # In[30]: x # Pythonでは,C言語と異なり,-1という添字で最後の要素にアクセスできる. # これは便利である. # In[31]: x[-1] # リストにはスライスという機能があり,添字の範囲指定で,リストの部分列を取り出せる. # In[32]: x[1:3] # In[33]: x[2:] # In[34]: x[:-1] # x[1:3]はリストxの添字1番から2番(3番の手前)までである. # 範囲の最後や最初を省略できる. # x[2:]はリストxの添字2番から最後までである. # x[:-1]はリストxの最初から,最後の手前までである. # In[35]: x[:] # 範囲の最初と最後の両方を省略するとリスト全体のスライスとなる. # これは一見意味が無いように思えるかもしれない. # しかし,リストのスライスはリストの(浅い)コピーを暗に作っているので,リストをコピーしたい場合には重宝する. # In[36]: x + x # リストは+演算子で連結できる. # ## 文字列の利用 # 文字列は文字のリストとでも言うべき扱いになっている. # In[37]: miyamoto = 'yuichiro' # In[38]: miyamoto[3] # In[39]: miyamoto[-1] # In[40]: miyamoto[2:7] # ただし,文字列はリストと異なり,変更はできない(immutableである). # In[41]: miyamoto[3] = 'a' # 文字列を変更したければ,新たに作って代入するしかない. # In[42]: miyamoto = miyamoto[:3] + 'a' + miyamoto[4:] # 2文字目まで + 'a' + 4文字目以降 # In[43]: miyamoto # In[44]: miyamoto = 'yuichiro' # あとの説明のために戻しておく. # ## 組み込み関数の利用 # Pythonには予め用意されている関数がある. # In[45]: len(x) # lenはリストや文字列の要素数を返す関数 # In[46]: len(miyamoto) # In[47]: sum(x[-1]) # sumはリストの要素の合計を返す関数,リストの要素は合計を計算できるようなものに限る. # In[48]: max(x[-1]) # maxはリストの最大の要素を返す関数 # In[49]: min(x[-1]) # minはリストの最小の要素を返す関数 # In[50]: min(miyamoto) # 文字の場合は辞書順で大きさが評価されるようだ. # 組み込み関数は他にもあるが,今回はここまでにしておく. # ## 標準ライブラリの利用 # Pythonでは,組み込み関数以外にも便利な関数がいろいろ用意されている. # 例えば,平方根や三角関数を計算してくれる数学関数などである. # 組み込み関数ではない関数は,そのままでは使えない. # 予め用意された関数などのかたまり(それらはモジュールとよばれる)を読み込む必要がある. # ここでは一例として数学関数モジュールmathを読み込んで使ってみる. # In[51]: import math # 数学関数のモジュールを読み込む. # モジュールを読み込む命令は # # ```python # import モジュール名 # ``` # # である. # これでそのモジュールを使えるようになる. # # モジュールで用意されている関数を使う際には # # ```python # モジュール名.関数名 # ``` # # とする. # # どのようなモジュールにどのような関数があるのかはインターネットで検索すればわかる. # In[52]: math.sqrt(2) # 2の平方根 # In[53]: math.pi # 円周率.関数だけでなく定数も用意されている. # In[54]: math.sin(math.pi / 6) # sin(30°) = 1/2 # 数値誤差のため,ピッタリ0.5とはならなかった. # ## 繰り返しの構文 # ここまでは,単独の命令だけを紹介してきた. # たとえ既存のモジュールを利用したとしても,単独の命令でできることはたかが知れている. # プログラムは,繰り返し命令などでたくさんの処理を行えるようになって初めて真価を発揮する. # 最も単純な例として,以下に,5回文字列を表示する命令を記す. # In[55]: i = 0 # 最初にiに0を代入しておく. while i < 5: # whileは繰り返し文のキーワードである.iが5未満の間は以下の2行の命令を繰り返す.2行下で毎回iを1増やしているので結局5回繰り返す. print(miyamoto) # printは引数の文字列を表示する組み込み関数である.文字列miyamotoの値,ここでは'yuichiro'を表示する. i = i + 1 # iを1増やす. # 上記の例から推測されるように,whileキーワードを用いた繰り返しの構文は # ```python # while 条件: # 命令1 # 命令2 # …… # ``` # である. # 条件が満たされる間,命令1,命令2,……が繰り返し実行される. # 繰り返される命令の範囲はインデントで区別される. # よってPythonのプログラミングにおいては,改行やインデントは重要である. # これはC言語やJavaとは大きく異る. # 繰り返しの構文にはforキーワードも使える. # forキーワードで上記と同じ処理を書くと,以下のようになる. # In[56]: for i in [0, 1, 2, 3, 4]: print(miyamoto) # 上記の例から推測されるように,forキーワードを用いた繰り返しの構文は # ```python # for 変数 in リスト: # 命令1 # 命令2 # …… # ``` # である. # リストの要素それぞれを変数に代入した場合に関して,命令1,命令2,……が実行される. # 繰り返される命令の範囲はやはりインデントで区別される. # よってPythonのプログラミングにおいては,改行やインデントは重要である. # 上記のforを用いた命令は5回繰り返すだけなので,リストは[0, 1, 2, 3, 4]で済んだ. # しかし,100万回繰り返すなどの場合には,リストを陽に書きたくない. # このような場合に便利なリスト生成関数(正確にはイテレータ)rangeが組み込み関数として用意されている. # In[57]: for i in range(5): # range(5)で[0, 1, 2, 3, 4]と同等 print(miyamoto) # rangeは # # - range(b)で「0から始まり,1ずつ増えて,b未満で終わる整数列」 # - range(a, b)で「aから始まり,1ずつ増えて,b未満で終わる整数列」 # - range(a, b, c)で「aから始まり,cずつ増えて,b未満で終わる整数列」 # # である. # # a, b, cには任意の整数を入れて良い. # ただし,range(7, 3, 1)とかにすると,7で始まり1ずつ増えて3未満で終わる整数はないので,何もないのと一緒となる.(繰り返されない.) # ただ表示するだけではつまらない. # # 以下に,1から20までの整数の合計を計算する命令を記す. # In[58]: s = 0 # sは合計を格納する変数 y = 1 # yは1から20までの整数が入る関数 while y <= 20: # whileは繰り返し構文のキーワード s = s + y # sをyだけ増やし y = y + 1 # yを1増やす # In[59]: s # 参考までに,同じ役割の命令をforを用いて以下に記す. # In[60]: s = 0 for i in range(1, 21): # iが1,2,...,20のそれぞれに関して実行される. s = s + i # In[61]: s # ## 条件分岐 # 次に,条件分岐の構文を紹介する. # 以下に,2017が素数でないならば'2017 is not prime'を表示する命令を記す. # In[62]: for i in range(2, 2017): # iが2,3,...,2016のそれぞれに関して以下の3行を実行する. if 2017 % i == 0: # 2017がiで割り切れるならば,素数ではないので, print('2017 is not prime.') # 素数ではないと表示し break # 繰り返しを終了する.命令breakは一番内側の繰り返し(この場合はforによる繰り返し)を終了する. # 実行すると何も表示されないので,どうやら2017は素数であるようだ. # (時間があったら他の数字でも試してみよう.) # # この例から推測されるように,ifキーワードを用いた条件分岐の構文は # ```python # if 条件: # 命令1 # 命令2 # …… # ``` # である. # 条件が満たされると,命令1,命令2,……が実行される. # 条件が満たされた場合に実行される命令の範囲はインデントで区別される. # # 条件分岐は以下の構文でも指定できる. # ```python # if 条件: # 命令1-1 # 命令1-2 # …… # else: # 命令2-1 # 命令2-2 # …… # ``` # 条件が満たされると,命令1-1,命令1-2,……が,条件が満たされないと命令2-1,命令2-2,……が実行される. # else以下は省略可能である. # # 先ほどの2017の素数判定はwhileを使うと以下のように書ける. # In[63]: n = 2017 i = 2 while i < n: # 3行下で毎回iを1増やしているので,これは「iが2からn-1のそれぞれに関して繰り返す」ということになる. if n % i == 0: # nをiで割った余りが0ならば割り切れるということなので print('2017 is not prime.') break # 命令breakは一番内側の繰り返し(この場合はwhileによる繰り返し)を終了する i = i + 1 # nがiで割り切れないならば,iを1増やして次に備える # In[64]: i # ちなみにここでiを表示すると,iには2017が入っている. # さらに,この素数判定はelseも使うと以下のように書ける. # In[65]: n = 2017 i = 2 while i < n: if n % i == 0: print('2017 is not prime.') break else: i = i + 1 # In[66]: i # もちろん結果は同じである. # # より一般に,2017以外の自然数が素数か否かを判定したい場合には,上記の処理においてnに最初に代入する値を変えれば良い. # しかし,その都度上記のコードを入力するのは面倒である. # そのような場合には,上記のコードをまとめたものを自作の関数として定義し,使いまわすと便利である. # ## 関数の定義と利用 # まず簡単な関数として,与えられた数の2倍を返す関数twiceを定義して使ってみる. # # 定義する前にtwiceという関数がすでにあるかないか実際に実行してみる. # In[67]: twice(2017) # twiceという名前の関数はないようなので,自分で定義してみる. # In[68]: def twice(x): y = 2 * x return y # この例から推測されるように,関数の定義は # ```python # def 関数名(引数): # 命令1 # 命令2 # …… # return 戻り値 # ``` # である. # 関数を実行すると,命令1,命令2,……が実行される. # returnキーワードがきたら,その直後の戻り値を返して関数は終了する. # # 特に値を戻す必要が無いならば,return命令はなくても良い. # しかし,後々の保守のためにはreturnを常に書くほうが良い. # 一度定義された関数は,組み込み関数と同様にinteratice shellで使える. # In[69]: twice(2017) # このtwiceの例で気がついたかもしれないが,関数の引数の型を指定する必要はない. # そもそも,Pythonには型を指定する宣言はない. # では,twiceの引数に整数以外を与えたらどうなるのか? # # それは試してみればわかる. # In[70]: twice(1.5) # In[71]: twice(miyamoto) # In[72]: twice([3, 1, 4]) # つまりここで定義した関数twiceは,数値を2倍する関数ではなく,「Pythonで乗算できるものならば,なんでも2倍する」関数である. # # これは便利に見えるが,諸刃の剣である. # 例えば,数値計算が目的なのにちょっとした間違いで文字列などを入れてしまったとしても「計算できる限りPythonは計算し続けてしまう」のである. # In[73]: lOO = 'These are L o o' twice(lOO) # もう少し複雑な関数を定義してみる. # # 以下に,引数nに2以上の自然数が与えられたとき,nが素数ならば'yes',nが素数でないならば'no'を返す関数is_primeを定義する. # In[74]: def is_prime(n): i = 2 while i < n: if n % i == 0: return 'no' # returnは関数を終了する命令としても使える. else: i = i + 1 return 'yes' # 関数終了時には,returnの直後に書かれているものが返される. # In[75]: is_prime(2017) # In[76]: is_prime(2019) # In[77]: is_prime(2021) # 素数の年(西暦)は当分先のようである. # # ここで,先程のtwiceと同様に,数値ではない値を関数is_primeに与えて実行してみよう. # In[78]: is_prime(miyamoto) # 今度は実行できなかった. # 整数i(=2)と文字列n(=miyamoto='yuichiro')の大小は比較できないからである. # # このように,Pythonには型の宣言はないものの,型の概念はある. # 変数の型は「値が代入されたときに,その値に従って」決まる. # # 定義した関数を用いてより高度な関数を定義できる. # 先ほどの素数判定関数is_primeを用いて,n以下の素数を表示する関数enumerate_prime_simplyを定義する. # In[79]: def enumerate_prime_simply(n): # この関数のようにreturnのない関数も定義できる i = 2 while i <= n: if is_prime(i) == 'yes': # 先ほど定義した関数is_primeを利用 print(i) i = i + 1 # In[80]: enumerate_prime_simply(20) # ここまでの知識を駆使すれば,より高度な関数を構築できる. # しかし,このinteractive shellを終えてしまったら,また構築し直しである. # 同じ関数を何度も構築しなくて良くするには,モジュールの構築が役立つ. # 次回は,モジュールの構築,そしてファイル入出力を学ぶ.