if文による条件分岐処理の基本文法は次のとおりです。
if [論理型]:
[処理] # ifの条件がTrueの場合
elif [論理型]:
[処理] # ifの条件がFalseで、elifの条件がTrueの場合
else:
[処理] # ifもelifもFalseの場合
end ifに相当する(ブロックの終わりを示す)文が無いことがわかると思います。これがPythonの見た目上の大きな特徴で、インデントによってブロックを判別しているのです。インデントはスペースでもタブでもよいのですが、プログラムを通して統一されている必要があります。通常、スペース4つがインデントに用いられます。ifなどの行末のコロンを忘れないようにしましょう。
if文の構造は必ずしもこの形である必要はなく、ifブロックのみや、if-elif、if-else、if-elif-elif-...などの形ももちろん可能です。
time_now = 15
if (time_now < 7) or (23 < time_now): # False
print("Sleeping")
elif time_now < 12: # False
print("Good morning!")
elif time_now < 17: # True
print("Good afternoon!")
else:
print("Good evening!")
繰り返しは、for文やwhile文を用います。
for文の基本文法は次のとおりです。
for n in [配列型]:
[処理]
例によってインデント記法です。forの行のコロンに気をつけましょう。 ここでnはダミー変数(文字はなんでもよい)で、配列型の要素を順に取ります。配列型としてはlist,tuple,strなどを用いるほか、range関数を用いることも多いです。range関数は次のような文法によって、等差数列を順に生成します(厳密には、range関数は「等差数列を順に返すオブジェクト」を生成しています。これをrange型のオブジェクトと呼ぶことができます)。
range(start,end,interval) # startからendまで(endは含まない)、間隔はinterval
range(start,end) # 省略するとinterval = 1
range(end) # start = 0, interval = 1
rangeはPython 2までは数列の入ったlistを返していたのですが、Python 3からrangeオブジェクトを返すようになりました(生成される数をメモリ上に格納しないため、メモリの節約になります)。使い方は同じです。
my_str = "orange"
for n in my_str:
print(n)
for i in range(10):
cube = i**3
print(cube)
For文においてもうひとつ便利な関数として、enumerateがあります。enumerate関数は次のような文法で、インデックスnと配列要素a[n]のtupleを返してくれます。
for (n,a) in enumerate([配列型]):
[処理]
for (n,a) in enumerate("apple"):
print(str(n)+", "+a)
while文の基本文法は次のとおりです。
while [論理型]:
[処理]
条件式(論理型の部分)がTrueである限り、処理を繰り返します。条件式がどこかでFalseになるようにするか、break文によってループから出ることでループを終わらせます。
i = 10.0
while i > 1:
print(i)
i = i / 2
# 引数を2乗して返す関数
def square(x):
return x**2
y = square(3) + square(4) # 3**2 + 4**2 = 25
print(y)
# 引数のうち大きい方を返す関数
def greater(x,y):
if x >= y:
return x
else:
return y
print(greater(4/3, 1))
# 引数なしやreturnなしの関数もできます
def bark():
print("Bow-wow!")
bark()
# オプション引数は、関数定義の際に[引数=デフォルト値]とすることでセットできます(通常の引数より後ろにおくこと)
def lunch(time,vegetarian=False):
if time < 11:
print("Too early for lunch!")
elif time > 16:
print("Too late for lunch!")
else:
if not vegetarian:
print("Hamburger!")
else:
print("Vegetarian hamburger!")
lunch(15)
lunch(15, vegetarian=True)
関数は基本的に値渡しです。
n = 10
def plusone(x):
x = x + 1
return x
print(plusone(n))
print(n)
リストやディクショナリなどはすべて参照として扱われるため、関数に渡した場合でも参照渡しのようになります。
# lis には参照が入る
lis = [10]
# 代入文でも参照が渡される
newlis = lis
# newlis を変更すると、その内容は lis にも伝播する
newlis[0] = 11
print("newlis", newlis)
print("lis", lis)
# 配列の中身を変更する関数
def plusone(x):
x[0] = x[0] + 1
# この関数を呼ぶと、関数の中で行われた変更は、呼び出し元の変数 lis に伝播する
plusone(lis)
print("plusone", lis)
詳細は述べませんが、関数内で変数を書き換える場合、その影響は関数内にとどまります(ローカルスコープ)。関数外で定義された変数を書き換えたい場合は、global文を用いてその変数がグローバル変数であることを宣言する必要があります。
x = 10
def try_to_rewrite_1():
global x
x = x + 10
def try_to_rewrite_2():
x = x + 10
print(x)
try_to_rewrite_1() # successful
print(x)
try_to_rewrite_2() # raises Error
汎用的な関数や定数群などを異なる複数のスクリプトで用いるときは、モジュールを用いるのが便利です。 モジュールの作り方は簡単で、基本的には独立したスクリプト(my_module.pyとします)の中に関数や定数を順に書いていくだけです。
たとえば、次のような内容のmy_module.pyを作ったとしましょう。
pi = 3.141592
def area(r):
return pi * r * r
このモジュールを使うには、my_module.pyがあるディレクトリで(あるいは後述のようにmy_module.pyへのパスを通して)、次のようにします。
import my_module
radius = 5.0
S = my_module.area(radius) # my_module内のarea関数
pi = 0
print(pi) # このスクリプト内の定数pi
print(my_module.pi) # my_module内の定数pi
モジュールで定義された変数や関数は、このスクリプト内の名前空間ではmy_module.[オブジェクト名]として扱われます。そのため、スクリプト内のオブジェクトとモジュール内の(しばしば把握しきれていない)オブジェクトとが干渉することが避けられます。
次のようなimportの方法もあります。
import my_module as mod # 別名をつける
print(mod.pi)
from my_module import pi # モジュール内の特定のオブジェクトのみをインポート
print(pi) # この場合、モジュール内の選ばれたオブジェクトがこのスクリプトの名前空間内に定義される
モジュール内のすべてのオブジェクトをスクリプトの名前空間にインポートする、
from my_module import *
という方法もありますが、モジュール内の把握しきれないオブジェクトがスクリプト内の変数と干渉するおそれがあるため、使わないことをお勧めします。
ここではmy_module.pyをスクリプトと同じディレクトリに置いた状態での使い方を紹介しましたが、色んな所から同じモジュールを呼び出したいときにはimportが参照するパスにmy_module.pyの場所を追加することができます。たとえばLinuxの場合は環境変数PYTHONPATHを用いたり、Pythonスクリプト上からsysモジュールを用いて次のようにパスを通すことができます。
from sys import path # pathは通っているパスが格納されているリストです
path.append("/home/username/where/module/is/located") # リストのappendメソッドで要素を追加
処理の高速化のため、一度読まれたモジュールはimport文があっても再び読まれません。 モジュールを修正して再び読み込んでほしい時には、セッションを再スタートする(IPythonなどを一度閉じる)か、importlibモジュール内のreload関数を用います。Python 2では組み込み関数としてreload()が定義されているため、importlibモジュールをインポートする必要はありません。
import my_module
# この時点でmy_module.pyを書き換えたとする
import my_module
# ここではモジュールの更新が適用されていない
from importlib import reload
my_module = reload(my_module)
# モジュールの更新が適用される
Python組み込みの便利なモジュールとして、ファイル管理などを通してシェルスクリプトを代替する機能を得られるosやshutil、正規表現を扱うre、日付を扱えるdatetimeなどがあります。numpy、scipy、matplotlibといったサードパーティのライブラリもモジュールの形で利用することになります。scipyなどの大きなモジュールはサブモジュールという階層構造をとっていることも多く、メモリ節約のために必要なサブモジュールだけをインポートすることも覚えておくとよいでしょう。
import numpy as np # NumPyはまるごとインポートしても大丈夫です
print(np.pi) # piやexp, cosなどの重要関数はnumpy直下にあります
x = np.random.rand(10) # randomサブモジュール内のrand関数
y = np.cos(x) # numpyモジュール内のcos関数
from scipy import special as sp # 特殊関数関連のサブモジュール
z = sp.erf(x) # 誤差関数
def func(x):
"""
This is an example docstring.
"""
sq = x*x # コメント
return sq
行を継続するときは、行の終わりに** \ **(バックスラッシュ)を入れます。
ただし、関数の引数が数多くある場合など、(), [], {}のカッコの中で改行するときには\を省略できます。
また、継続行の行頭の開始位置に関して制約はありません。
x = 3
y = 1 + 2*x + 3*np.sin(x) \
+ 4*np.cos(x) + 5*np.exp(x)
some_list = [1, 2, 3, 4, 5,
6, 7, 8, 9, 10]