5. 基本的な Python の使い方
5.1. 基本のデータ型
Python は様々な数値を組み込みで扱えるように設計されています. 大別すると数値を扱うためのデータ型と,それを集合として扱うための コンテナ型に分けられます.
5.1.1. 数値型
5.1.1.1. 整数型
1In [1]: 1 + 1
2Out[1]: 2
3In [2]: a = 4
4In [3]: a
5Out[3]: 4
5.1.1.2. 浮動小数点型
1In [1]: c = 2.1
2Out[1]: 2.1
とまぁ,ここまでは普通です.
5.1.1.3. 複素数型
1In [1]: a = 1 + 1.5j
2In [2]: type(a)
3Out[2]: <type 'complex'>
4In [3]: a * a
5Out[3]: (-1.25+3j)
6In [4]: a.real
7Out[4]: 1
8In [5]: a.imag
9Out[5]: 1.5
といったように特殊な操作なしで複素数演算ができます.
5.1.1.4. ブール型
さらに,ブール値(真/偽)もひとつの型として扱えます.
1In [1]: 3 > 4
2Out[1]: False
3In [2]: a = (3>4)
4In [3]: a
5Out[4]: False
6In [5]: type(a)
7Out[5]: <type 'bool'>
といったように論理値を扱うことが可能です.
これらの整数型では,基本的な算術加減乗除演算 +, -, *, /` や, 剰余 %%,べき ** といった演算がサポートされています.
注釈
Python 3 以降で整数商を求めるには '//' を演算子として用います.
1In [1]: print(5//2)
2Out[1]: 2
3In [2]: print(5/2)
4Out[2]: 2.5
明示的な型変換は,変換したいクラス (整数値: int, 実数型: float, 複素数型: complex, ブール型: bool) といったキーワードを用いて変換します.
1In [1]: float(1)
2Out[1]: 1.0
3In [2]: complex(1)
4Out[2]: (1+0j)
5.1.2. コンテナ
Python ではデータの集合を扱うための入れ物(コンテナ)を用意してくれています. リスト,辞書,集合,タプルなどがありますが.ここではリストを主として説明し, 文字列,辞書,タプルと説明を行います.
5.1.2.1. リスト
リストはデータ(以下オブジェクトと呼びます)を順序付き集合として扱うためのコンテナです. 要素となるオブジェクトは異なる型を格納できます. リストは [ , ] を用いて定義することができます. また,各要素にはリストを表すオブジェクトに [] でインデックスを指定することでアクセスが可能です.
1In [1]: l = [10, 20, 30, 40, 50]
2In [2]: ll = [1, 2.0, 3+0j, '4', 5]
3In [3]: l[2]
4Out[3]: 30
5In [4]: ll[-2]
6Out[4]: '4'
インデックスは 0 からリストの左からカウントしますが, 負のインデックスが指定された場合,右からカウントします. l = [10, 20, 30, 40, 50] の場合:
リスト l |
|||||
|---|---|---|---|---|---|
データ列 |
10 |
20 |
30 |
40 |
50 |
通常インデックス |
l[0] |
l[1] |
l[2] |
l[3] |
l[4] |
負のインデックス |
l[-5] |
l[-4] |
l[-3] |
l[-2] |
l[-1] |
のようなインデックスによって要素が指定されます.
注釈
インデックスは 0 からカウントします.混同しないようにしましょう
さらにインデックスの範囲は スライス と呼ぶ部分指定方法で得ることができます. スライスは, 始点と終点をコロンで区切った 表記になります. たとえば, l` を上述のリストとすると,インデックスが,2から始まって, 4未満の値からなる部分リスト(つまり l[2] と l[3])を得るには `l[2:4]` といった指定のしかたとなります.
1In [1]: l
2Out[1]: [10, 20, 30, 40, 50]
3In [2]: l[2:4]
4Out[2]: [30, 40]
注釈
l[start:stop]` と書いた場合, start <= i < stop` を満たす i が条件となります. stop-1 までの値しか要素としてとりえないことに注意が必要です.
また,全てのスライスは必須ではなく,省略が可能です.
1In [1]: l
2Out[1]: [10, 20, 30, 40, 50]
3In [2]: l[:3] # l[0], l[1], l[2] までの要素
4Out[2]: [10, 20, 30]
5In [3]: l[3:] # l[3], l[4]
6Out[3]: [40, 50]
という書き方になります.
さらにスライスの3番目の値を指定すればインデックスの数え方を2個おきとかにすることも可能です.
l[start:stop:stride]
というのはリスト l から l[start] から l[stop-1] までの要素を stride おきに取ってくることを 意味します.
1In [1]: l
2Out[1]: [10, 20, 30, 40, 50]
3In [2]: l[0:5:2] # l[::2] と書いてもおk
4Out[2]: [10, 30, 50]
5In [3]: l[1:5:2] # l[1::2] と書いてもおk
注釈
蛇足ですが,
l[3] # 要素
と
l[3:4] # スライス
とは意味合いが違うので注意が必要です.上の例は要素の値(スカラー量)を取り出してますが,下の例は 要素1個からなるリスト(スライス)を意味します.
注釈
上記の例では # 記号 を用いてますが,これはコメントです. python のコメントは,# で表され # 以下,行末までがコメントと見做されます
要素の追加と削除は l.append() などといったリストを操作する関数 (メソッド)を使えばよいのですが, かんたんなのは + などの演算子を使って,ひっつけてやることです.
1In [1]: l
2Out[1]: [10, 20, 30, 40, 50]
3In [2]: l + [60, 70] # + を使って別のリストを結合
4Out[2]: [10, 20, 30, 40, 50, 60, 70]
5In [3]: l * 2 # * を使って繰り返す
6Out[3]: [10, 20, 30, 40, 50, 10, 20, 30, 40, 50]
なお + 演算はリスト以外のものを貼り付けることはできません.
1In [1]: l + 60 # N.G. 60 は,リストではないので l+[60] ならおk
2Traceback (most recent call last):
3 File "<stdin>", line 1, in <module>
4TypeError: can only concatenate list (not "int") to list
5In [2]: l + [60] # OK [60] は1個の要素からなるリスト
6[10, 20, 30, 40, 50, 60]
7In [3]: l.append(60) # append を使う場合は整数値指定でもおk
8In [4]: l
9Out[4]: [10, 20, 30, 40, 50, 60]
注釈
append のようにリストを操作するメソッドは,C++ は Java のようなオブジェクト指向に 基づいた記述法です.これらのメソッドはオブジェクトを操作するために用いられるもので, オブジェクトの後ろに ピリオド をつけて記述します. もし,これらのメソッドを探したければ,インタプリタに python ではなく Jupyter Notebook や ipython を使って tab を使って保管することで検索するのが一番簡単だと思います.
1In [2]: l # ipython を使うとプロンプトが異なる
2Out[2]: [10, 20, 30, 40, 50]
3In [3]: l. # ドットまで打って tab で補完
4l.append l.extend l.insert l.remove l.sort
5l.count l.index l.pop l.reverse
6In [3]: l.
といったような補完が可能です.またヘルプ機能を使うとメソッドやオブジェクトに 関するドキュメントが読めます.
1In [4]: help(l)
2# リスト l に関するヘルプが表示されるはず
3In [5]: help(l.append)
4# リスト l に対する append() メソッドに関するヘルプが表示されるはず
リストに関するこれ以上の詳しい説明は python のチュートリアル (初心者向けの解説,ただし英語) [EtutList] や, 日本語で書かれている(けどすこしバージョンの古い)のチュートリアルなどを [JtutList] を 参照してください. リストをスタックやキューとして使用する方法なども載っています.
5.1.2.2. 文字列
文字列は,引用符文字 (', ", """) などによってくくられる文字です. 下記の例では, s0 から s3 の文字列オブジェクトを設定しています.
1In [1]: s0 = 'Hello world'
2In [2]: s1 = "Hello world"
3In [3]: s2 = """
4Hi,
5what's happen?
6"""
7In [4]: s2 = 'こんにちは,世界'
python では シェルの文法とは違い,クォート文字自体に意味はありません. なので, s0 と s1 に設定している文は全く同じ意味を持っています. s2 の例ではトリプルクォート ( """ で表現) を使っていますが, このクォートでくくられた場合は,複数行に渡る文字列の設定ができます. 日本語も普通に扱えます.
5.1.2.2.1. 文字のリストとしての文字列
また,文字列は,リストのスライスを用いて表すこともできます.
1In [1]: s0
2Out[1]: 'Hello world'
3In [2]: s0[1]
4Out[2]: 'e'
5In [3]: s0[2:5]
6Out[3]: 'llo'
文字列は 変化不能なオブジェクト (immutable) です. すなわち, C 言語のときのようにインデックス指定をして文字を書き換えることは できません
1In [1]: a = 'Hello World.'
2In [2]: a[2] = 'z'
3Traceback (most recent call last):
4File "<stdin>", line 1, in <module>
5TypeError: 'str' object does not support item assignment
ただし,文字列に属するメソッドを使うことで,書き換えることはできます.
1In [1]: a
2Out[1]: 'Hello World.'
3In [2]: a.replace( 'l', 'z', 1 ) # 一番最初の 'l' 1個を 'z' に
4Out[2]: 'Hezlo World.'
5In [3]: a.replace( 'l', 'z' ) # すべての 'l' を 'z' に
6Out[3]: 'Hezzo Worzd.'
注釈
jupyter ノートブック環境などでは意識することが無いですが, コンソールなどで日本語などの utf-8 コードは print 関数を使ってやらないと コード値そのものが出てくる場合があるのでびっくりしないようにしてください.
1In [1]: s2
2Out[1]: u'\u3053\u3093\u306b\u3061\u306f\uff0c\u4e16\u754c'
3In [2]: print(s2[2:5])
4Out[2]: 'にちは'
5.1.2.2.2. 文字列に関する幾つかのメソッド
Python は,オブジェクト指向言語としての側面を持っています. 文字列に対しても幾つかの メソッド と呼ばれる操作関数が用意されています.
前述の文字列に対する replace() メソッドも文字列というオブジェクトに関する操作になります. メソッドを使うには,文字列オブジェクトに関して, ピリオド/ドットでつないで呼び出すことができます. (ピリオド/ドットでつなぐのは Java, C++ の流儀ですが,ここでも同じ呼び出し方法です)
例えば,文字列 'This is a pen. That is a pencil' のような文字列を, 空白文字で区切ってリストにする.なんてことをしようと思ったら, split() メソッドを使ってやればよく
1In [1]: s = 'This is a pen. That is a pencil'
2In [2]: s.split()
3Out[2]: ['This', 'is', 'a', 'pen.', 'That', 'is', 'a', 'pencil.']
4In [3]: slst = s.split()
5In [4]: slst[3]
6Out[4]: 'pen.'
のように文字列を空白で区切って分解したリストを返してくれます. なので,リストを別の変数で受け取ってやれば分解した部分文字列を扱うことができます.
また別の文字(例えば,文中のピリオド)を区切り文字として使って分解するには, メソッドの引数に区切り文字を指定してやればよいだけです.
1 In [5]: s.split( '.' )
2 Out[5]: ['This is a pen', ' That is a pencil', '']
という感じの2文に分解できることがわかります.
文字列メソッドに関して語り始めると長いので後は省略しますが ここらへんのドキュメントを眺めて(使って遊んでみて)ください.
http://www.python.jp/doc/release/library/stdtypes.html#string-methods
なお,メソッドは文字列を変数に代入しなくても直接適用することもできます.
1In [1]: 'The future will be better than tomorrow.'.replace( 'tomorrow', 'today' )
2Out[1]: 'The future will be better than today'
のように,文字列に直接 replace することができます. (文字列はダン・クエールの演説から引っ張ってきました)
5.1.2.2.3. その他よく見かける使い方
また,文字列の便利な使い方としては, % を用いた置換があります.C 言語の printf のフォーマット分のようなものを想像してもらえれば良いのですが,
1In [1]: a = 'x = %d, y = %f, string = "%s"'
2In [2]: a
3Out[1]: 'x = %d, y = %f, string= "%s"'
4In [3]: a % (1, 0.1, 'hello' )
5Out[3]: 'x = 1, y = 0.100000, string= "hello"'
% で始まる部分を後方で指定される数値に置き換えることができます. これを使うと後述する for 文 のような繰り返し構造を用いて,規則的な名前を持つファイル名を 作成したりすることができます. たとえば, data.00 から data.09 までのデータファイルがあって, 順に処理しないといけないような場合には,下記のような記述が可能です.
1indxs = [1, 2, 3, 4, 5, 6, 7, 8, 9]
2fname_tmpl = 'data.%02d'
3for i in indxs:
4 fname = fname_tmpl % i
5 print(fname) # ためしに fname を表示させてみる.
6 # ここに fname を使った処理を書いていく
ただし,最近の python では, % 表記はあまり使われません. 文字列 (str`型) の `format() 関数が使われます. 文字列の中には,中括弧 { } でプレースホルダを作り,そこに埋め込んでいきます.
1In [1]: a = 'x = {}, y = {}, string = "{}"'
2In [2]: a.format(1, 0.1, 'hello')
3Out[2]: 'x = 1, y = 0.1, string= "hello"'
フォーマット指定するにはプレースホルダ {} の中で`{:02d}` のように書きます.
1indxs = [1, 2, 3, 4, 5, 6, 7, 8, 9]
2fname_tmpl = 'data.{:02d}'
3for i in indxs:
4 fname = fname_tmpl.format(i)
5 print(fname) # ためしに fname を表示させてみる.
6 # ここに fname を使った処理を書いていく
さらに, format すら使わずに文字列の前に f をつけて直接変数を埋め込む方法が最近のやり方になります.
1indxs = [1, 2, 3, 4, 5, 6, 7, 8, 9]
2for i in indxs:
3 fname = f'data.{i:02d}' # 文字列に変数 i をフォーマット付きで書いている
4 print(fname)
5.1.2.3. 辞書
辞書型は キー (key) と値 (value) の対応付け を行うテーブルで,他の言語では 連想配列やハッシュやマップといった呼ばれ型をされます. たとえば,果物と色の対応表をつくるとしましょう.'りんご' なら '赤' とか 'ばなな' なら '黄' というやつです. 辞書の要素は,コロンで区切られたペアを使って表現します.コロンの左側にくるのが キーで,右側が値となります.
1In [1]: coltbl = {'apple':'red', 'banana':'yellow', 'orange':'orange', 'peach':'pink' }
2In [2]: coltbl['banana'] # バナナの色を表示させてみる
3Out[2]: 'yellow'
4In [3]: coltbl.keys # どのような key があるのかを表示
5Out[3]: ['apple', 'banana', 'orange', 'peach']
6In [4]: coltbl.values # どのような値があるのかを表示
7Out[4]: ['red', 'yellow', 'orange', 'pink']
8In [5]: 'orange' in coltbl # 'orange' というキーが coltbl 内あるか?
9Out[5]: True
5.1.2.4. タプル
タプルは,変化不可能な(immutable) なリストです.参照はリストと同じように出来ますが, 値を変化させることができません. 丸括弧で囲うことで記述します.
1In [1]: t = 123, 456, 'abc'
2In [2]: t
3Out[2]: (123, 456, 'abc')
4In [3]: t[1]
5Out[3]: 456
6In [4]: t[2] = 789 # 書き換えはできない
7Traceback (most recent call last):
8 File "<stdin>", line 1, in <module>
9TypeError: 'tuple' object does not support item assignment
5.1.3. 代入演算
すでにここまでで代入演算を使っているのですが,代入演算は,オブジェクトと変数名に対応づける 操作です.これは変更可能なオブジェクトの属性や要素を変更したりするために使われます. 代入演算は, = という記号で記述されます.
1>>> a = 2
2>>> b = [1, 2, 3]
3>>> a = b
代入演算の操作では,
まず = で結ばれた右辺が評価され,対応するオブジェクトが生成されます
つぎに生成されたオブジェクトに名前が付けられます
といった手順で操作が行われます.例えば上記例での a = 2 といった例では,まず 値 '2' を持つデータオブジェクトが生成され,これに対して変数名 a の対応付け (束縛, binding) が行われます.
同様に b = [1,2,3] という例でも,リストが生成されてから,このリストに b という名前での参照 対応付けが行われます. ここで a = b とすると, a の対応付けが変化し,先ほどの 2 という整数オブジェクトから,リストに参照先が移動します.
そのけっか, a の対応先が b の指しているリストになり, 2 というデータオブジェクトが忘れ去られます. (忘れ去られたデータはガベージコレクタという仕組みにより自動的に資源として回収されます). この結果 a のリストを書き換えると b のリストの値が変わるということが起こるので 注意が必要です.
1In [1]: a[1] = 20
2In [2]: b
3Out[2]: [1, 20, 3]
5.1.4. 引用元
英語版 Python チュートリアル http://docs.python.org/tutorial/datastructures.html#more-on-lists
日本語版 Python チュートリアル http://www.python.jp/doc/release/tutorial/datastructures.html#more-on-lists
5.2. 制御構造
制御構造はコードが実行される順序を制御します.
5.2.1. if / elif/ else による条件分岐
In [1]: if 2**2 == 4:
...: print('ただしい')
...
ただしい
ブロックの範囲は インデント で決まります. C/C++` や Java` のように中括弧でくくるのではなく,Python はインデントによる 見た目 でソースコードを解釈します. いままでインデントして来なかった人たちは, 見やすいコード を習得するようにしてください.
以下の行を Python インタプリタで打ち込んで下さい. ただし インデントの深さに注意してください Jupyter Notebook や IPython はコラム記号 : の後に自動的にインデントを深くしてくれます. インデントを減らすにはバックスペースキーでスペース4つ分移動します. 論理ブロックを抜けるためには2回エンターキーを押します.
In [1]: a = 10
...: if a == 1:
...: print('a は 1です')
...: elif a == 2:
...: print('a は 2です')
...: else:
...: print('たくさん')
...:
Out[1]: たくさん
インデントはスクリプトを書く場合も必須です. 練習として, 上の行の内容を同じインデントで condition.py というスクリプトに
打ち込んで 端末のコマンドラインから python の引数としてファイル名を渡して実行させてみてください.
$ python condition.py
あるいは Jupyter Notebook 上で \%run コマンドを使ってもらっても良いです.
あとは a` の値を色々と書き換えて,予想通りに動くかどうかも確認しましょう.
こういう確認作業はわりと大事です. 思っていることと書いたことが違う ということは良くあります.
なので,どこまで正しく動いているかを確認していくことが大事です.
5.2.2. for / range による繰り返し
C 言語などで出てきた for 文と同じ繰り返しの文法です.
少し違うのは range() 関数をつかって,繰り返しのリストを生成するところが
ちょっとだけ違います.
range() 関数は Python 3 ではイテレータを返すので,list に与えるとリストを生成します.
以下を実行してみればわかりますが,range(n) で,0 から n-1 までのリストぽいもの(イテレータ)を生成し,これを list() に与えると
リスト化されます.
In [1]: list(range(10))
Out[1]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
これを使って繰り返し構文を書くと以下のようになります.
In [1]: for i in range(4):
...: print(i)
...:
0
1
2
3
これは,以下のように書くのと一緒です.
In [1]: for i in [0,1,2,3]
...: print(i)
つまり for 文は,リストやタプルから,ひとつひとつ要素を選択して実行していってくれるということにます.
なので,タプルを用いて以下のような書き方も可能です.
In [1]: for word in ('cool', 'powerful', 'readable'):
...: print('Python is %s' % word)
...:
Python is cool
Python is powerful
Python is readable
5.2.2.1. リスト内包表記
さらにリストを使いやすくするために,python では,以下のようなリスト内で繰り返しを行うような表記も許しています.
In [1]: [i**2 for i in range(4)]
Out[1]: [0, 1, 4, 9]
この例では i を 0 から 3 まで回して,その時の i**2 (iの二乗) をリストとして与える演算を行なっています.
5.2.3. while による繰り返し
典型的な C 形式の while ループも使用可能です. (以下の例は Mandelbrot の問題と呼ばれる問題です.)
In [1]: z = 1 + 1j
In [2]: while abs(z) < 100:
...: z = z**2 + 1
...:
In [3]: z
Out[3]: (-134+352j)
5.2.4. break / continue による繰り返しの制御
繰り返しを制御する方法として, break 文や continue 文が使用可能です.
break 文は for / while ループの中から抜けることができます.
In [1]: z = 1 + 1j
In [2]: while abs(z) < 100:
...: if z.imag == 0:
...: break
...: z = z**2 + 1
...:
continue 文はループの反復を進めます.
In [1]: a = [1, 0, 2, 4]
In [2]: for element in a:
...: if element == 0:
...: continue
...: print(1. / element)
...:
1.0
0.5
0.25
5.2.5. 条件式 に関する補足
if 文による分岐や,繰り返しに用いられる条件文などは 条件式 と呼ばれ,Bool 型が用いられます. 条件分岐を例とすると形式としては ..
if 条件式 :
のように書かれます.このとき
偽と評価されるもの:
0 に等しい数 (0, 0.0, 0+0j)
空のコンテナ (list, tuple, set, dictionary, ...)
False, None といった Python の組み込み値
真と評価されるもの:
上記以外の空でないあらゆるオブジェクト
が,真偽判定の根拠となります.
ちょっと注意しておいてほしいのは,以下の条件式です.
a == b などといった論理演算値
論理的に等価かどうか調べる:
In [1]: 1 == 1.0 Out[1]: True
a is b といったオブジェクトの同一性を比べるもの
同一性を調べる→2つのオブジェクトが同じオブジェクトかどうか
In [1]: 1 is 1.0 Out[1]: Falseこの場合は整数の 1 と浮動小数の 1.0 を比較しているので別物ということになります.
a in b
in は,データの集まり b の中に a が含まれているかを判断してくれます
In [1]: b = [1, 2, 3] In [2]: 2 in b Out[2]: True In [3]: 5 in b Out[3]: Falseb が辞書の場合, 辞書のキーに a が含まれているか調べます.
5.3. 関数の書き方,使い方
5.3.1. 関数定義の基本
さて,ここでは関数定義の使い方をやってみます. Python 関数に必要なのは,入力に与える情報です. (返すのは基本型や好きな型のオブジェクトを返すことができます.)
まずは文字を表示するだけの関数を作ってみます.
1def test():
2 print('in test() function')
キーワード def で始まる部分は関数の定義を表します.続いて関数名,カッコで括った
引数情報(この場合は引数なしです)がきます.そしてコロン : を記述することで,
その次の行以降のインデントされたブロック単位が関数となります.
注釈
関数の定義部分は,ブロックがわかるように 必ず インデント して(emacs の場合はタブキーを使う)書いてください. 制御構造のところでもやりましたが,Python は, C言語と違い,インデント無しだと,ブロックがキチンと解釈されません.
5.3.2. 関数を使ってみる
関数を使う場合まで含めた記述をすると上の例は下記の 形になります.
1In [1]: def test():
2 ...: print('in test() function')
3 ...:
4In [2]: test()
5in test() function
というように python のプロンプト上で単に呼びだしを書けば実行してくれます. 呼び出すときは,引数がなくても () をつけて呼び出してください. ちなみに,単に test だけでプロンプトから python インタープリンタに渡すと, test で与えられるオブジェクトが 関数(で,メモリ上のどこにマッピングされているか)であることを 表示します.
1In [1]: test
2Out[1]: <function test at 0x1027ccaa0>
マッピングされている場所(アドレス)はヒトによって違うと思います.
5.3.3. 引数
引数には,必須の引数(固定引数)とオプションの引数(名前付き引数)の2種類が あります.
5.3.3.1. 固定引数
固定引数は C 言語などでやった引数と同じ考え方です. もし,適当な引数がほしければ,
1In [1]: def test1(param):
2 ...: print('in test1(): ', param)
3 ...:
のように定義してあげれば良いだけです.但し,型宣言をする必要は ありません.なので param には数値だろうが文字列だろうが,与えれば print 関数が対応している限り表示を行います. ただし引数を与えなければエラーになります.
1In [1]: test1(10.3)
2in test1(): 10.3
3In [2]: test1('hogehoge')
4in test1(): hogehoge
5In [3]: test1() # <-- 引数なし
6Traceback (most recent call last):
7 File "<stdin>", line 1, in <module>
8TypeError: test1() takes exactly 1 argument (0 given)
5.3.3.2. 名前付き引数
名前付き引数はデフォルトの値を設定することで,呼び出し側で その引数を省略させることができます.
1In [1]: def test2(param='hogehoge'):
2 ...: print('in test2(): ', param)
3 ...:
4In [2]: test2()
5in test2(): hogehoge
6In [3]: test2(10.3)
7in test2(): 10.3
といったように省略したときは,関数定義の際に指定した 'hogehoge' という 文字列オブジェクトが変数 param に与えられ,関数が実行されます. 一方,引数に 10.3 といった数値を指定して動かすことが可能です.
上記のように名前付き引数が一つだけの場合は,名前を付けずに渡しても良いのですが, 複数個の名前付き引数がある場合には,呼び出すときに,変数名を指定して渡すことも できます.
1In [1]: def test3(p1='hoge', p2=2):
2 ...: s = p1 * p2
3 ...: print('in test3(): ', s)
4 ...:
5In [2]: test3()
6in test3(): hogehoge
7In [3]: test3(4) # p1 に 4 が設定される
8in test3(): 8
9In [4]: test3(p2=3, p1='piyo') # 名前を指定すれば順番を入れ替えてもおk
10in test3(): piyopiyopiyo
注釈
デフォルトの値は関数が呼び出されたときではなく, 定義されたときに評価されます. なので,デフォルト値を変えたい場合は,もう一度定義してやる必要があります.
5.3.4. 返り値
関数はオプションとしてオブジェクトを返すことができます.この時には return 文を使います. たとえば,半径 r が与えられた時の円の面積を返す関数を定義するならば以下のようになるでしょう.
1In [1]: def CircleArea(r):
2 ...: return r * r * 3.14159
3 ...:
4In [2]: CircleArea(4)
5Out[2]: 50.265439999999998
なお,python 3.9 以降では,関数の引数に型ヒントをつけることができます. たとえば,先ほどの CircleArea 関数を以下のように書くことができます.
1In [1]: def CircleArea(r: float) -> float:
2 ...: return r * r * 3.14159
3 ...:
4In [2]: CircleArea(4)
5Out[2]: 50.265439999999998
このように書くことで,引数 r は float 型であること,返り値も float 型であることを 明示的に示すことができます. 型ヒントはあくまでヒントであり、Python の実行時には強制されませんが,コードの可読性を向上させるために有用です.
また,C 言語などではできなかった複数の返り値やリストを返すこともできます. たとえば,数値の配列が与えた時に,配列の個数,最小値,最大値を返すような関数を作りたければ,
1In [1]: def func(a):
2 ...: return((len(a), min(a), max(a)))
3 ...:
4In [2]: x = [1, 24, 5, 68, 28, -8]
5In [3]: func(x)
6Out[3]: (6, -8, 68)
などという,3個の値をパックしたタプルが返ってきます.
型ヒントを使うと以下のように書くことになります. ちょっと試しのような関数にヒントを使うかどうかはおまかせしますが,.py ファイルではキチンと書くと良いと思います.
1In [1]: from typing import List, Tuple
2In [2]: def func(a: List[int]) -> Tuple[int, int, int]:
3 ...: return (len(a), min(a), max(a))
4 ...:
5In [3]: x = [1, 24, 5, 68, 28, -8]
6In [4]: func(x)
7Out[4]: (6, -8, 68)
蛇足ですが,返ってきた複数値を変数として受け取りたい場合は,タプルか変数を明示して受け取ることが可能です.
1In [1]: def func(a):
2 ...: return((len(a), min(a), max(a)))
3 ...:
4In [2]: x = [1, 24, 5, 68, 28, -8]
5In [3]: lx, xmin, xmax = func(x) # 複数の変数を受取
6In [4]: xmin
などのように変数を並べたタプルで受け取ることができます.
注釈
デフォルトでは関数は,何もないと言うこと表す None を返します
5.3.5. 関数定義のまとめ
関数の定義方法をまとめると下記のようになります.
def キーワード;
続けて関数の名前
丸括弧の間に関数の引数を与え
コロン
関数の本体; インデント を忘れずに
そしてオプションとして値を返すために return object
- 付帯事項として,
引数は,固定引数と名前付き引数があり,名前付き引数はデフォルト値を設定できる.
関数は複数の値を返すことができる.
Python 3.9 以降では型ヒントを使って引数と返り値の型を明示的に示すことができる.