---
tags: Python
---
# Python3 Note
## 1. 対話型インタープリタを起動する
:::info
※特に指定がない場合、このサイトのすべてのコードは対話型インタープリタで記述しています。
:::
1. コマンドプロンプトやターミナル等を起動させる
1. 以下のコマンドを叩く

1. 「>>>」が表示されればOK
1. pythonコードが認識されないエラーが表示される場合、パスが通っていないと思われるため、システム変数にパスを追加するか、Pythonのインストールをし直す。この際、パスを通すチェックボックスにチェックを入れてインストールし直す必要がある。
1. "Hello Python!"を表示させる
1. 以下のコマンドを入力してエンター
1. `>>> print('Hello Python!')`

1. 2を実行すると、上記のように表示される
### 1.1 Pythonファイルを使う場合(Hello Python!)
1. テキストエディタに以下のコマンドを入力
1. `print('Hello Python!')`
1. 上記のファイルを"HelloPython.py"という名前で保存する
1. コマンドプロンプト、またはターミナルを開き、上記で作成したファイルが保存されているディレクトリに移動する

1. 以下のコマンドを叩く
1. `python HelloPython.py`

---
## 2. 変数を扱う
Pythonのデータ型
| 型名 | 型 | 取り得る値 |
| -------- | -------- | -------- |
| ブール型 | boolean | True / False |
| 整数型 | int | 任意のサイズ(longよりも大きな数値が表現可能) |
| 浮動小数点数型 | float | 小数点を持つ数値 |
| 文字列型 | string | [’]または["]で囲われた値 |
### 2.1. 変数名に使用できない値
* 先頭が数字(例:1a)
* 以下の予約語
* False, class, finally, is, return, None, continue, for, lambda, try, True, def, from, nonlocal, while, and, del, global, not, with, as, elif, if, or, yield, assert, else, import, pass, break, except, in, raise
### 2.2. 数値演算
```python=
>>> # 宣言
>>> testInt1 = 2
>>> testInt2 = 4
>>> testInt3 = 7
>>> # 四則演算
>>> testInt1 + testInt2
6
>>> testInt2 - testInt1
2
>>> testInt1 * testInt2
8
>>> testInt2 / testInt1
2.0
>>>
>>> # 整数の除算(小数点以下切捨て)
>>> testInt2 // testInt1
2
>>> # 剰余
>>> testInt3 % testInt2
3
>>> # 指数
>>> testInt1 ** testInt2
16
```
```python=+
>>> # 対象の変数に対して演算を行う場合(例は足し算)
>>> testInt1 += 1
>>> testInt1
3
>>> # 上記と同様にすべての演算について「[演算子]=」が使用できる
```
### 2.3. 文字列
```python=
>>> # 宣言
>>> # 以下のstr1とstr2は同様の結果となる
>>> str1 = 'test'
>>> str2 = "test"
>>> str1
'test'
>>> str2
'test'
```
> 文字列にシングルクォートやダブルクォートを含める場合
```python=+
>>> str3 = 'you said "Hi!"'
>>> str3
'you said "Hi!"'
>>> str3 = "you said 'Hi!'"
>>> str3
"you said 'Hi!'"
```
> トリプルクォート
>> 対話型インタープリタが行う自動エコーの場合、改行は改行コード(\n)となって表示されるが、print()の出力では改行される
>> [color=#907bf7]
```python=+
>>> str3 = '''this is test.
... String triple quote test!!!'''
>>>
>>> # 対話型インタープリタが行う自動エコーの場合
>>> str3
'this is test.\nString triple quote test!!!'
>>>
>>> # printした場合
>>> print(str3)
this is test.
String triple quote test!!!
```
> +による連結
```python=+
>>> str4 = 'python test '
>>> str5 = 'oh my hogehoge'
>>> str4 + str5
'python test oh my hogehoge'
```
> *によるくり返し
```python=+
>>> loopStr = 'na ' * 4
>>> loopStr
'na na na na '
```
> []による文字の抽出
```python=+
>>> letters = 'abcdefghijklmnopqrstuvwxyz'
>>> letters[0]
'a'
>>> letters[1]
'b'
>>> letters[-1]
'z'
>>> # 文字列はイミュータブル(書き換えできない)なので、以下はできない
>>> letters[1] = 'a'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment
>>>
>>> # 文字列を書き換える場合はreplaceやスライス(後述)の組み合わせを使用する
>>> letters.replace('a','A')
'Abcdefghijklmnopqrstuvwxyz'
```
> スライス
```python=+
>>> # [ start:end:step ] によるスライス
... # ・[:] 先頭から末尾までのシーケンス全体を抽出する
... # ・[start:] startオフセットから末尾までのシーケンスを抽出する
... # ・[:end] 先頭からend-1オフセットまでのシーケンス全体を抽出する
... # ・[start:end] startオフセットからend-1オフセットまでのシーケンス全体を抽出する
... # ・[start:end:step] step文字ごとにstartオフセットからend-1オフセットまでのシーケンス全体を抽出する
>>>
>>> letters[:]
'abcdefghijklmnopqrstuvwxyz'
>>> letters[20:]
'uvwxyz'
>>> letters[12:15]
'mno'
>>> letters[-3:]
'xyz'
>>> letters[18:-3]
'stuvw'
>>> # 先頭から末尾まで7文字毎に文字を取り出す
>>> letters[::7]
'ahov'
>>> letters[4:20:3]
'ehknqt'
>>> # 以下の二つは結果が同じ
>>> letters[-1::-1]
'zyxwvutsrqponmlkjihgfedcba'
>>> letters[::-1]
'zyxwvutsrqponmlkjihgfedcba'
>>> # スライスは間違ったオフセットにも寛容(OutOfIndexにならない)
>>> letters[-50::]
'abcdefghijklmnopqrstuvwxyz'
>>> letters[-50::-50]
''
>>> letters[:71]
'abcdefghijklmnopqrstuvwxyz'
```
> lenによる長さの取得
```python=+
>>> len(letters)
26
>>> letters[len(letters)-1:len(letters)]
'z'
```
> splitによる分割とjoinによる結合
```python=+
>>> todos = 'get gloves,get mask,give cat vitamins,call ambulance'
>>> splittodo = todos.split(',')
>>> splittodo
['get gloves', 'get mask', 'give cat vitamins', 'call ambulance']
>>> # セパレータを指定しないと空白文字(改行、スペース、タブ)のシーケンスを使う
>>> todos.split()
['get', 'gloves,get', 'mask,give', 'cat', 'vitamins,call', 'ambulance']
>>> jointodo = ','.join(splittodo)
>>> jointodo
'get gloves,get mask,give cat vitamins,call ambulance'
>>>
```
> その他、多彩な文字列操作が行えるが、ここでは紹介を控える
> 興味がある人は標準ドキュメント(http://bit.ly/py-docs-strings)を参照してください。
---
### 2.4. リスト、タプル、辞書、集合
#### 2.4.1. リスト操作
> リスト作成
```python=
>>> empty_list = []
>>> empty_list_func = list()
>>> weekday = ['Sunday', 'Monday', 'Tuesday']
>>> empty_list
[]
>>> empty_list_func
[]
>>> weekday
['Sunday', 'Monday', 'Tuesday']
```
> 要素の取り出し(内包する要素を超えるとIndexErrorが発生する)
```python=+
>>> weekday[0]
'Sunday'
>>> weekday[-1]
'Tuesday'
```
> スライスによる取り出し(2つ目はリストの順序を逆順にするトリック)
> スライスの使い方は文字列の場合と同様、ただし、スライスで取り出したリストの要素はリスト
```python=+
>>> weekday[0:2]
['SUN', 'Monday']
>>> weekday[::-1]
['Tuesday', 'Monday', 'SUN']
```
> 要素の書き換え
```python=+
>>> weekday[0] = 'SUN'
>>> weekday[0]
'SUN'
>>> weekday[1]
'Monday'
```
> appendで末尾に追加
```python=+
>>> weekday.append('THU')
>>> weekday
['SUN', 'Monday', 'Tuesday', 'THU']
```
> extendまたは+=を使ったリストの結合
```python=+
>>> weekend = ['SAT']
>>> weekday.extend(weekend) # weekday += weekend でも同様
>>> weekday
['SUN', 'Monday', 'Tuesday', 'THU', 'SAT']
```
> delで指定したオフセットの要素の削除
```python=+
>>> del weekday[1]
>>> weekday
['SUN', 'Tuesday', 'THU', 'SAT']
```
> insertでオフセットを指定した要素の追加(誤ったオフセットでもエラーは出ない)
```python=+
>>> del weekday[1]
>>> weekday.insert(1, 'MON')
>>> weekday
['SUN', 'MON', 'Tuesday', 'THU', 'SAT']
```
> removeによる値に基づく要素の削除
```python=+
>>> weekday.append('Tuesday')
>>> weekday
['SUN', 'Monday', 'Tuesday', 'THU', 'Tuesday']
>>> weekday.remove('Tuesday') # 一つずつしか消えない
>>> weekday
['SUN', 'MON', 'THU', 'SAT', 'Tuesday']
>>> weekday.remove('Tuesday')
>>> weekday
['SUN', 'MON', 'THU', 'SAT']
```
> popでオフセットを指定して要素を取り出して削除する
```python=+
>>> weekday.insert(2, 'Tuesday')
>>> weekday
['SUN', 'MON', 'Tuesday', 'THU', 'SAT']
>>> weekday.pop(2) # 何も指定しないと-1と同様に末尾を返す
'Tuesday'
>>> weekday
['SUN', 'MON', 'THU', 'SAT']
```
> indexで要素の値から対象のオフセットを知る
```python=+
>>> weekday.index('MON')
1
```
> inで値の有無を知る(一つでもあればTrue)
```python=+
>>> 'THU' in weekday
True
>>> 'TUE' in weekday
False
```
> countで含まれている個数を取得する
```python=+
>>> weekday.count('MON')
1
>>> weekday.count('TUE')
0
>>> weekday.append('MON')
>>> weekday
['SUN', 'MON', 'THU', 'SAT', 'MON']
>>> weekday.count('MON')
2
```
> joinで文字列へ変換
```python=+
>>> ','.join(weekday)
'SUN,MON,THU,SAT,MON'
>>>
```
> sortで要素の並べ替え
>> sortは対象のリスト自体をソートする
>> sortdedはソートされたリストのコピーを返す
```python=+
>>> numbers = [8,4,7,32.7,3,51,1,5.0]
>>> abc = ['b','y','w','o','p','t','bab','bob','ok']
>>> # 数値はデフォルトで昇順にソートされる
>>> sorted_numbers = sorted(numbers)
>>> sorted_numbers
[1, 3, 4, 5.0, 7, 8, 32.7, 51]
>>> # sorted()の場合、元のリストはそのまま
>>> numbers
[8, 4, 7, 32.7, 3, 51, 1, 5.0]
>>> # sortだと、元のリストが書き換わる
>>> numbers.sort()
>>> numbers
[1, 3, 4, 5.0, 7, 8, 32.7, 51]
>>> # 「reverse=true」にすれば逆順にもできる
>>> numbers.sort(reverse=True)
>>> numbers
[51, 32.7, 8, 7, 5.0, 4, 3, 1]
>>> # 文字列はデフォルトでアルファベット順
>>> abc.sort()
>>> abc
['b', 'bab', 'bob', 'o', 'ok', 'p', 't', 'w', 'y']
>>> # 文字列と数値が混ざったリストなどをソートしようとするとエラーが発生する
>>> maxi = ['a',1,4]
>>> maxi.sort()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: '<' not supported between instances of 'int' and 'str'
```
> lenで長さの取得
```python=+
>>> len(abc)
9
```
> =による代入とcopyによるコピー
```python=+
>>> b = abc
>>> b
['b', 'bab', 'bob', 'o', 'ok', 'p', 't', 'w', 'y']
>>> abc[0] = 'test'
>>> abc
['test', 'bab', 'bob', 'o', 'ok', 'p', 't', 'w', 'y']
>>> # bはabcと同じリストオブジェクトを参照しているので、どちらかの操作は両方に反映される
>>> b
['test', 'bab', 'bob', 'o', 'ok', 'p', 't', 'w', 'y']
>>> b[1]='number1'
>>> b
['test', 'number1', 'bob', 'o', 'ok', 'p', 't', 'w', 'y']
>>> abc
['test', 'number1', 'bob', 'o', 'ok', 'p', 't', 'w', 'y']
>>>
>>> # オリジナルとは別のオブジェクトを作成する場合は以下の方法でコピーする
>>> b = abc.copy()
>>> c = list(abc)
>>> d = abc[:]
>>> b
['test', 'number1', 'bob', 'o', 'ok', 'p', 't', 'w', 'y']
>>> c
['test', 'number1', 'bob', 'o', 'ok', 'p', 't', 'w', 'y']
>>> d
['test', 'number1', 'bob', 'o', 'ok', 'p', 't', 'w', 'y']
>>> # abcに変更を加えても他のリストには影響しない
>>> abc[0] = '111111111'
>>> abc
['111111111', 'number1', 'bob', 'o', 'ok', 'p', 't', 'w', 'y']
>>> b
['test', 'number1', 'bob', 'o', 'ok', 'p', 't', 'w', 'y']
>>> c
['test', 'number1', 'bob', 'o', 'ok', 'p', 't', 'w', 'y']
>>> d
['test', 'number1', 'bob', 'o', 'ok', 'p', 't', 'w', 'y']
```
> 他のデータ型からリストへの変換
```python=+
>>> # 文字列をリストに変換する
>>> list('cat')
['c', 'a', 't']
>>>
>>> # タプル(次に紹介する)をリストに変換する
>>> tuple = (1,2,3)
>>> list(tuple)
[1, 2, 3]
>>>
>>> # splitで分割するしてリストに変換する
>>> birthday = '1981/10/11'
>>> birthday.split('/')
['1981', '10', '11']
```
> リストのネスト構造
```python=+
>>> south_fruits = ['banana','mango']
>>> vege_fruits = ['tomato','water melon']
>>> fruits = [south_fruits, vege_fruits, 'apple']
>>> fruits
[['banana', 'mango'], ['tomato', 'water melon'], 'apple']
```
#### 2.4.2. タプル
> タプルとリストの比較
>> ・タプルは消費スペースが小さい
>> ・タプルはイミュータブル(書き換え不可)のため、要素を誤って書き換える危険がない
>> ・タプルは辞書のキーとして使用できる
>> ・名前付きタプルは、オブジェクトの単純な代用品として使える
>> ・関数の引数はタプルとして渡される
>
> 通常のプログラミングではタプルよりもリストや辞書を使うことが多い。
> タプルの作成
```python=+
>>> # 空のタプル
>>> tuple = ()
>>> tuple
()
>>> # 1つ以上の要素を持つタプルはカンマで区切る(要素が1つの場合も末尾にカンマをつけて作る)
>>> tuple = 'test',
>>> multi_tuple = 'a','b','c' # 複数要素の場合の末尾のカンマは省略可能
>>> tuple
('test',)
>>> multi_tuple
('a', 'b', 'c')
```
> タプルのアンパック(同時に複数の変数を定義できる)
```python=+
>>> multi_tuple
('a', 'b', 'c')
>>> a,b,c = multi_tuple
>>> a
'a'
>>> b
'b'
>>> c
'c'
```
> 一時変数を使わずに値の交換が可能!
```python=+
>>> key = 'key'
>>> value = 'value'
>>> key, value = value, key
>>> key
'value'
>>> value
'key'
```
#### 2.4.3. 辞書
> 辞書は要素の順序が管理されていないので、要素を選択するときにオフセットは使用しない。代わりに値を「Key:Value」形式で持つため、このKey(一意である)を使用する。
> Keyは文字列の場合が多いが、Pythonのイミュータブル型なら何でもよい。
> 宣言(Json形式を思い出してもらえると嬉しい)
```python=
>>> empty_dict = {}
>>> empty_dict
{}
>>> dict = {'a':'aaa','b':'bbb','c':'ccc'}
>>> dict
{'a': 'aaa', 'b': 'bbb', 'c': 'ccc'}
```
> dictを使った変換
```python=+
>>> # リストのリスト
>>> lol = [['a','A'],['b','B'],['c','C']]
>>> dict(lol)
{'a': 'A', 'b': 'B', 'c': 'C'}
>>>
>>> # 2文字の文字列のリストを変換
>>> los = ['aA','bB','cC']
>>> dict(los)
{'a': 'A', 'b': 'B', 'c': 'C'}
>>>
>>> # 他にもリストのタプルやタプルのリスト、2文字のタプルなども変換可能
```
> 要素の追加・変更
```python=+
>>> # 追加
>>> loldict = dict(lol)
>>> loldict
{'a': 'A', 'b': 'B', 'c': 'C'}
>>> loldict['d'] = 'd'
>>> loldict
{'a': 'A', 'b': 'B', 'c': 'C', 'd': 'd'}
>>>
>>> # 修正
>>> loldict['d'] = 'D'
>>> loldict
{'a': 'A', 'b': 'B', 'c': 'C', 'd': 'D'}
```
> updateによる辞書の結合
```python=+
>>> # 同一のキーをもっていた場合は結合される側のキーが優先される
>>> los
['aA', 'bB', 'cC', 'eE', 'eE']
>>> losdict = dict(los)
>>> losdict
{'a': 'A', 'b': 'B', 'c': 'C', 'e': 'End'}
>>> loldict.update(losdict)
>>> loldict
{'a': 'A', 'b': 'B', 'c': 'C', 'd': 'D', 'e': 'End'}
```
> 要素の削除
```python=+
>>> # delによる指定したキー要素の削除
>>> del loldict['e']
>>> loldict
{'a': 'A', 'b': 'B', 'c': 'C', 'd': 'D'}
>>>
>>> # clearによる要素の全削除
{'a': 'A', 'b': 'B', 'c': 'C', 'd': 'D'}
>>> losdict
{'a': 'A', 'b': 'B', 'c': 'C', 'e': 'End'}
>>> losdict.clear()
>>> losdict
{}
```
> inを使ったキーの有無確認
```python=+
>>> loldict
{'a': 'A', 'b': 'B', 'c': 'C', 'd': 'D'}
>>> 'a' in loldict
True
>>> 'z' in loldict
False
>>>
```
> 要素の取得
```python=+
>>> loldict['a']
'A'
>>>
>>> # 存在しないキーを指定するとエラーが発生する
>>> loldict['z']
True
>>> 'z' in loldict
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'z'
>>> # 先にinでキーが存在するか否かを確認する必要がある
>>>
>>> # get関数を使用して取得する
>>> loldict.get('a')
'A'
>>> # オプションを指定するとオプションが返却される
>>> loldict.get('z', 'Not z')
'Not z'
>>> # オプションを指定せず、キーがなければNoneを返す(コンソールには何も表示されない)
>>> loldict.get('z')
```
> keysによるすべてのキーの取得
```python=+
>>> loldict.keys()
dict_keys(['a', 'b', 'c', 'd'])
```
> valuesによるすべての値の取得
```python=+
>>> loldict.values()
dict_values(['A', 'B', 'C', 'D'])
```
> itemsによるすべてのキー/バリューペアの取得
```python=+
>>> loldict.items()
dict_items([('a', 'A'), ('b', 'B'), ('c', 'C'), ('d', 'D')])
```
> =による代入とcopyによるコピーはリストの場合と同様
#### 2.4.4. 集合
> 機械学習などの場面では重要な概念になる(ただし、ライブラリがほとんどこなしてしまうので集合を使用してガシガシコーディングすることは少ないだろう)が、Webアプリケーションがメインのここでは割愛する。
---
## 3. 処理構造
### 3.1. if elif else
```python=
>>> def test(intA):
... if intA == 0:
... print('0!')
... elif intA == 1:
... print('1!')
... else:
... print('No!')
...
>>> test(0)
0!
>>> test(1)
1!
>>> test(2)
No!
>>>
```
### 3.2. 比較演算子
| 演算子 | 説明 |
| -------- | -------- |
| == | 等しい |
| != | 等しくない |
| < | より小さい |
| <= | 以下 |
| > | より大きい |
| >= | 以上 |
| in ... | 要素になっている |
### 3.3. Trueとは何か?
| FalseとみなされるPythonの値 | 説明 |
| -------- | -------- |
| False | BooleanのFalse |
| None | Null |
| 0 | 整数の0 |
| 0.0 | floatの0 |
| '' | 空文字列 |
| [] | 空リスト |
| () | 空タプル |
| {} | 空辞書 |
| set() | 空集合 |
> 上記を使用して、Falseだけではなく空データ構造かどうかをチェックできる
```python=
>>> some_list = []
>>> if some_list:
... print("There's something in here")
... else:
... print('empty!')
...
empty!
```
### 3.4. ループ
#### 3.4.1. While
```python=
>>> count = 1
>>> while count <= 5:
... print(count)
... count += 1
...
1
2
3
4
5
```
##### 3.4.1.1. breakによるループ中止
```python=
>>> while True: # 無限ループ
... # コンソールでのインプットを受け取る
... inputdata = input('type q to quit:')
... if inputdata == 'q':
... break
... print(inputdata.capitalize())
...
type q to quit:a # <-[a]を入力した
A
type q to quit:b # <-[b]を入力した
B
type q to quit:q # <-[q]を入力したことでループが終了
```
##### 3.4.1.2. continueによる次のイテレーションの開始
```python=
>>> while True: # 無限ループ
... # コンソールでのインプットを受け取る
... value = input('type q to quit: ')
... if value == 'q': # 終了する
... break
... if value == 'a': # 次のイテレーションへ移動
... continue
... print(value.capitalize())
...
type q to quit: a # <-[a]を入力したのでコンティニュー
type q to quit: b # <-[b]を入力した
B
type q to quit: test # <-[test]を入力した
TEST
type q to quit: q # <-[q]を入力したことでループが終了
```
##### 3.4.1.3. elseによるbreakのチェック
> whileループが正常終了(breakせずに終了)したら、制御はオプションのelse節に渡される。何かをチェックするためにwhileループを書き、それが見つかったらすぐにbreakするときに使う。
```python=
>>> numbers = 1,3,5
>>> position = 0
>>> while position < len(numbers):
... number = numbers[position]
... if number % 2 == 0:
... print('Found even number', number)
... break
... position += 1
... else: # breakが呼び出されていない
... print('No even number found')
...
No even number found
```
#### 3.4.2. for
> whileとの差異を示す。forのほうがよりPythonらしいコードになり、コードのバイト数の節約にもなる(JavaやC#でいうところの拡張for文にあたる。イテレータを利用したループ処理。)
> breakやcontinue、elseの処理方法はwhileの場合と同じため割愛する。
> ただし、for文のelseの場合、breakが使用されなかったか否かを判定するためにはフラグを定義してそれを判定する必要がある。
```python=
>>> numbers = 1,2,3,4,5
>>> position = 0
>>> while position < len(numbers):
... print(numbers[position])
... position += 1
1
2
3
4
5
>>>
>>> # forで書き直し
>>> for number in numbers:
... print(number)
...
1
2
3
4
5
```
#### 3.4.3. rangeによる数値シーケンスの作成
あらかじめリストやタプルなどの大きなデータ構造体を作ってそこに値を格納しなくても、指定した範囲の数値ストリームを返すことができる。range(start, end, step)というスライスと似た形式で使用し、startを省略すると0が先頭になる。endは必須引数。
```python=
>>> # 0~2までのプリント
>>> for tmp in range(0,3):
... print(tmp)
...
0
1
2
>>>
>>> # 0~2までのリスト作成
>>> list(range(0, 3))
[0, 1, 2]
>>>
>>> # 2~0までのプリント
>>> for tmp in range(2, -1, -1):
... print(tmp)
...
2
1
0
```
### 3.5. 関数
「3.1. if elif else」で使用した以下の記述が関数
```python=
>>> def test(intA):
... if intA == 0:
... print('0!')
... elif intA == 1:
... print('1!')
... else:
... print('No!')
...
>>> test(0)
0!
>>> test(1)
1!
>>> test(2)
No!
>>>
```
* 「def」で定義する
* 「()」内に引数を指定する
* 戻り値はreturnで指定するだけで宣言に加えない
> 位置引数
>> 先頭から順に対応する位置の仮引数にコピーされる
>> 他言語と同様な一般的な引数の指定方法
```python=+
>>> test(0)
0!
```
> キーワード引数
>> 仮引数に名前を指定して実引数を指定する方法で、関数定義と引数の順序が異なっていても構わない。
>> 関数を呼び出す側の指定の仕方による。
>> 位置引数とキーワード引数の両方を使って関数を呼び出すことが可能だが、先に一引数を指定しなければならない。
```python=+
>>> test(intA=0)
0!
```
> デフォルト引数の指定
>> 仮引数にはデフォルト値を指定することができる。呼び出し元が対応する実引数を渡してこなかったときに使用される。
>> :::danger
>> デフォルト引数が計算されるのは、**関数が実行された時ではなく、定義されたとき**なので、リストや辞書型などのミュータブル(変更可能)なデータ型をデフォルト引数として使ってしまうと、**前回の呼び出しでセットされた値が残ってしまい**、想定とは違う動きになってしまうので注意が必要 :fire:
>> :::
```python=+
>>> def test2(intA, intB=10):
... if intA == 0:
... print('0!')
... elif intA == 1:
... print('1!')
... else:
... print('No!')
... if intB == 10:
... print('Default')
...
>>> test2(10)
No!
Default
>>> test2(1,2)
1!
```
> *による位置引数のタプル化
>> 仮引数の一部として*を使うと、可変個の位置引数をタプルにまとめてその仮引数にセットすることができる。
```python=+
>>> def print_args(*args):
... print('tuple:', args)
...
>>> print_args(1,2,'a','arg','oh!!')
tuple: (1, 2, 'a', 'arg', 'oh!!')
```
> \**によるキーワード引数の辞書化
>> 二つのアスタリスクを使えば、キーワード引数を1個の辞書にまとめることができる。引数の名前は辞書のキー、引数の値は辞書の値になる。
```python=+
>>> def print_kwargs(**kwargs):
... print('keyword args:', kwargs)
...
>>> print_kwargs(wine='merlot', entree='mutton', dessert='macaroon')
keyword args: {'wine': 'merlot', 'entree': 'mutton', 'dessert': 'macaroon'}
```
> その他の有効な関数の使い方(実行例なしで紹介のみ)
>> ・関数内関数:関数の中で関数を定義することができる
>> ・クロージャ:他の関数によって動的に生成される関数
>> ・無名関数(ラムダ関数):一つの文で表現される名前のない関数(GUIでコールバック関数を定義するときなどに特に役に立つ)
>> ・ジェネレータ:反復処理のたびに最後に呼び出された場所を管理し、次の値を返す。通常の関数とは、値を「return」ではなく「yield」で返すだけの違い。
>> ・デコレータ:ソースコードを書き換えずに既存の関数に変更を加えたい場合に使用する
### 3.6. エラー処理
try, except を使用し、以下のような使い方をする。
```python=
>>> short_list = [1, 2, 3]
>>> while True:
... value = input('Position [q to quit]? ')
... if value == 'q':
... break
... try:
... position = int(value)
... print(short_list[position])
... except IndexError as err:
... print('Bad index:', position)
... except Exception as other:
... print('Something else broke:', other)
...
Position [q to quit]? 1
2
Position [q to quit]? 0
1
Position [q to quit]? 2
3
Position [q to quit]? 3
Bad index: 3
Position [q to quit]? two
Something else broke: invalid literal for int() with base 10: 'two'
Position [q to quit]? q
```
---
## 4. オブジェクトとクラス
### 4.1. クラス定義
> 最も単純なクラス
```python=
>>> class test():
... pass
```
> コンストラクタを作ってみる
```python=
>>> class Person():
... # __init__()は初期化メソッドの匿名
... # selfは作られたオブジェクト自体を参照することを示す
... def __init__(self):
... pass
```
> nameというパラメータを追加する
```python=
>>> class Person():
... def __init__(self, name):
... self.name = name
>>>
>>> # Personクラスの実装
>>> master = Person('satoshi')
>>> print(master.name)
satoshi
```
### 4.2. 継承
> コードの再利用
```python=
>>> class Car():
... def exclaim(self):
... print('I am a car!')
... def run(self):
... print('I am run 50 km/h!')
...
>>> class porsche(Car):
... def run(self): # オーバーライド
... print('I am run 250 km/h!')
... def need_a_push(self): # 独自メソッド
... print('A little help here?')
...
>>> acar = Car()
>>> car_porsche = porsche()
>>> acar.exclaim()
I am a car!
>>> acar.run()
I am run 50 km/h!
>>> acar.need_a_push()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Car' object has no attribute 'need_a_push'
>>>
>>> car_porsche.exclaim()
I am a car!
>>> car_porsche.run()
I am run 250 km/h!
>>> car_porsche.need_a_push()
A little help here?
```
### 4.3. 親クラスの呼び出し
> super
```python=
>>> class Person():
... def __init__(self, name):
... self.name = name
>>> class EmailPerson(Person):
... def __init__(self, name, email):
... super().__init__(name) # superで親クラスを呼び出して意味のある継承にする
... self.email = email
>>>
>>> # Personクラスの実装
>>> hide = EmailPerson('hide', 'hide@gmail.com')
>>> hide.name
'hide'
>>> hide.email
'hide@gmail.com'
```
### 4.4. モジュールではなくクラスとオブジェクトを使う場合
モジュールは Python の定義や文が入ったファイルのこと。
* 動作は同じだが、内部状態は異なる複数のインスタンスを必要とする場合はオブジェクトが最も役立つ
* クラスは継承をサポートするが、モジュールはサポートしない
* 何かを一つだけ必要とするときはモジュール
* Pythonのモジュールはプログラムに何度参照されても1個のコピーしかロードされないため、シングルトンとして使える
* 複数の値を持つ変数があり、これらを複数の関数に引数として渡せる場合、それをクラスとして定義したほうがよい時がある
* 問題にとって最も単純な方法を使うこと、辞書・リスト・タプルはモジュールよりも単純で小さく高速で、クラスよりも普通は単純
## 5. DB操作(SQLite)
以下のようなzooというテーブルを作るとする
* critter
* 動物の名前、主キー(可変長文字列)
* count
* その動物の現在の個体数(整数)
* damages
* 動物との触れ合いによる現在の損失額
```python=
>>> import sqlite3
>>> conn = sqlite3.connect('enterprise.db')
>>> curs = conn.cursor()
>>> curs.execute('''CREATE TABLE zoo (critter VARCHAR(20) PRIMARY KEY, count INT, damages FLOAT)''')
<sqlite3.Cursor object at 0x0000018393366A40>
```
> SQLクエリのような長い文字列を生成するときには、Pyhonのトリプルクォートが便利
> レコードを追加する(INSERT INTO)
```python=+
>>> curs.execute('INSERT INTO zoo VALUES("duck", 5, 0.0)')
<sqlite3.Cursor object at 0x0000018393366A40>
>>> curs.execute('INSERT INTO zoo VALUES("bear", 2, 100.0)')
<sqlite3.Cursor object at 0x0000018393366A40>
```
> プレースホルダーを使用したより安全な方法
> 3つの疑問符を使って3個の値を挿入する予定だということを示してから、execute()関数への引数として3個の値のリストを渡している。クォートなどの面倒な細部を処理し、SQLインジェクションからシステムを守ってくれる。
```python=+
>>> ins = 'INSERT INTO zoo (critter, count, damages) VALUES(?, ?, ?)'
>>> curs.execute(ins, ('weasel', 1, 2000.0))
<sqlite3.Cursor object at 0x0000018393366A40>
```
> すべての情報を引き出す(SELECT)
```python=+
>>> curs.execute('SELECT * FROM zoo')
<sqlite3.Cursor object at 0x0000018393366A40>
>>> rows = curs.fetchall()
>>> print(rows)
[('duck', 5, 0.0), ('bear', 2, 100.0), ('weasel', 1, 2000.0)]
```
> 個体数順のソート(ORDER BY)
```python=+
>>> # 昇順
>>> curs.execute('SELECT * FROM zoo ORDER BY count')
<sqlite3.Cursor object at 0x0000018393366A40>
>>> curs.fetchall()
[('weasel', 1, 2000.0), ('bear', 2, 100.0), ('duck', 5, 0.0)]
>>>
>>> # 降順
>>> curs.execute('SELECT * FROM zoo ORDER BY count DESC')
<sqlite3.Cursor object at 0x0000018393366A40>
>>> curs.fetchall()
[('duck', 5, 0.0), ('bear', 2, 100.0), ('weasel', 1, 2000.0)]
```
> あひるの個体数が増えたので編集する(UPDATE)
```python=+
>>> curs.execute('UPDATE zoo SET count=? WHERE critter=?',(10, 'duck'))
<sqlite3.Cursor object at 0x0000018393366A40>
>>> conn.commit()
>>> curs.execute('SELECT * FROM zoo ORDER BY count DESC')
<sqlite3.Cursor object at 0x0000018393366A40>
>>> curs.fetchall()
[('duck', 10, 0.0), ('bear', 2, 100.0), ('weasel', 1, 2000.0)]
```
:::info
**別サイト(Pythonチートシートへのリンク)** [こちら](https://www.atmarkit.co.jp/ait/spv/2001/21/news012.html)
:::