【Python】基本的な文法まとめ

#Pythonとは
![python-logo-master-v3-TM-flattened.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1075243/24eda476-94b9-3ab8-7a07-3444f24bdc7d.png)

>Python（パイソン）はインタープリタ型の高水準汎用プログラミング言語である。グイド・ヴァン・ロッサムにより創り出され、1991年に最初にリリースされたPythonの設計哲学は、有意なホワイトスペース(オフサイドルール)の顕著な使用によってコードの可読性を重視している。その言語構成とオブジェクト指向のアプローチは、プログラマが小規模なプロジェクトから大規模なプロジェクトまで、明確で論理的なコードを書くのを支援することを目的としている。
参照元：[Python Wikipedia](https://ja.wikipedia.org/wiki/Python)

wikipediaさん、ありがとう(^^)

#Pythonの特徴
Pythonはインタプリタ上で実行することを前提に設計されている。
Pythonに加え、JavaScript、PHP、Ruby、Perlなどが代表的なインタプリター言語。

- **動的な型付け**
- **ガベージコレクション**
    - コンピュータプログラムが動的に確保したメモリ領域のうち、不要になった領域を自動的に解放する機能
- **マルチパラダイム**（マルチ思想・枠組み）
    - マルチパラダイムとは、論理型、関数型、オブジェクト指向、データフローコンカレントなど、多数のパラダイムを内包する言語ということ。
- **リフレクション**
    - プログラムの実行過程でプログラム自身の構造を読み取ったり書き換えたりする技術のこと。
    - プログラムの構造などの情報は低レベルコード（アセンブリ言語など）にコンパイル変換される過程で失われるが、リフレクションをサポートする言語は、その情報を生成されるコードの中にメタデータとして保存して、モジュール・クラス・オブジェクト等の言語の要素が内部からアクセス可能に。
    - 用途は、実行時にしか分からない情報を取得、その情報を使った処理のため


#宣言
##変数
- 使用できる文字は a ～ z 、 A ～ Z 、 0 ～ 9 、アンダーバー(_)、漢字など
- 一文字目に数値(0～9)は使用できない
- 一文字目にアンダーバーは使用できるが特別な用途で使用されているケースが多いので通常は使用しない方がいい
- 大文字と小文字は区別される
- 予約語は使用できない
- 一部の他の言語のように、変数の定義のみを行うことはできない


```python
# OK
name1 = '太郎'
_x = 'x' # 非推奨
年齢 = 30
a, b = 1, 2
c, d = 3, "4"

# NG
7point = 250
return = 'return' # 予約語
name5 # ここでエラー
name5 = '太郎'

# ケース違いは別変数
str = "Hello"
STR = "World"

# 再代入OK
name = "Suzuki"
name = "Tarou"

# 別のデータ型の値の代入もOK
age = '二十'
age = 20

# 変数を変数に代入可能、同じメモリ上の値を参照することになる
num1 = 10
num2 = num1

# メモリ上の値の参照先が変わる。 num1は20に、num2は10のまま
num1 = 10
num2 = num1
num1 = 20
```
###予約語一覧
※versionによって異なります。

|  |  |  |  |  |
|:-:|:-:|:-:|:-:|:-:|
| False | await | else | import | pass |
| None | break | except | in | raise |
| True | class | finally | is | return |
| and | continue | for | lambda | try |
| as | def | from | nonlocal | while |
| assert | del | global | not | with |
| async | elif | if | or | yield |

##リスト
リストの要素の操作は
追加：`append, extend, insert`
削除：`clear, pop, remove, del`

```python
# []
empty_list = []

# [0, 0, 0]
l = [0] * 3

# [0, 1, 2, 0, 1, 2, 0, 1, 2]
l = [0, 1, 2] * 3

# 要素のリストがそれぞれ異なるオブジェクトとして扱われる書き方
# [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
l = [[0] * 3 for i in range(3)]
```

##タプル
```python
# 要素数1のタプルは,が必要なので注意
# (0, 0, 0)
tuple = (0,) * 3

# ('a', 'b', 33)
tuple = ('a', 'b', 33)
```

##array型
```python
# コンストラクタに初期化したリストを渡せばOK
# array('i', [0, 0, 0])
import array
array = array.array('i', [0] * 3)
```

##関数
###基本的な宣言

```python
# 関数はdefブロックで定義する。括弧()内に引数、returnで戻り値を指定
# 戻り値の型は引数および関数の処理に依存
def func_name(arg1, arg2, arg3, ...):
    Do some process
    return value

# 戻り値なし
# returnを省略した関数はNoneを返す
def hello():
    # Do some process
    pass # 何もしないpass

# returnの後を省略した関数はNoneを返す
def hello():
    return

# 明示的にNoneを書いてもOK
def hello():
    return None
```
###複数の戻り値を指定する場合
```python
# 複数の値をカンマ区切りするとタプルが返される
def func_return_multiple_value(a, b):
    return a+b, a*b, a/b

# タプル型で戻ってくる
# (3, 2, 0.5)
x = func_return_multiple_value(1, 2)

# 別々の変数に代入することも可能
# x==3, y==2, x==0.5
x, y, z = func_return_multiple_value(1, 2)
```

###キーワード引数を使う場合
```python
# 呼び出し時にキーワード引数[引数名=値]として値を渡せる
# キーワードで指定した以降の引数はすべてキーワードで指定
def func(a, b, c):
    Do some process

# OK
func(b=33, c=333, a=3)
func(3, c=333, b=33)

# NG: a=3がキーワードだから
func(a=3, 33, 333)
```
###位置専用引数を使う場合

```python
# 位置専用引数（Python3.8以降）
# [/]より「前」の引数が位置専用引数に、つまり a,b
def func_position_only(a, b, /, c):
    Do some process

# OK
func_position_only(3, 33, 333)
func_position_only(3, 33, c=333)

# NG: a,bは位置専用
func_position_only(a=3, b=33, c=333)
```
###キーワード専用引数を使う場合
```python
# [*]より「後」の引数がキーワード専用引数
# [*]より前の引数は、位置でもキーワードでも指定可能
def func_keyword_only(a, b, *, c):
    Do some process

# OK 
func_keyword_only(3, 33, c=333)
func_keyword_only(3, c=333, b=33) 

# NG: 333はc=333になるべき
func_keyword_only(3, 33, 333)
```
###位置専用引数とキーワード専用引数の組み合わせ
```python
# [/]より前は位置専用引数
# [*]より後はキーワード専用引数
# [/]と[*]の間は位置でもキーワードでもOK
def func_pos_kw_only(a, /, b, *, c):
    Do some process

# OK
func_pos_kw_only(3, 33, c=333)
func_pos_kw_only(3, c=333, b=33)

# NG
func_pos_kw_only(3, 33, 333)
func_pos_kw_only(a=3, b=33, c=333)
```
```python
# ちなみに、[/]より前に[*]を使うとSyntaxError
# NG
def func_pos_kw_only(a, *, b, /, c):
```
###関数定義時にdefault値設定
```python
# Set Default Value: c=333 
def func_default_val(a, b, c=333):
    Do some process

# a=3, b=33, c=333
func_default_val(3, 33)

# a=3, b=33, c=222
func_default_val(3, 33, 222)

# デフォルト引数を、デフォルト値指定なしの引数の前に置くとエラー
# NG: bの前にa=1がある
def func_default_val(a=1, b, c=100):
    Do some process
```
###可変超引数を使う場合
※位置引数との組み合わせや、タプルと辞書との組み合わせは順番に注意が必要
#### [*]をつける場合：タプル型
```python
# 複数の引数をタプル型として渡す
def func_tuple_args(*args):
    Do some process

# (3, 33)
func_tuple_args(3, 33)

# (3, 33, 333, 3333)
func_tuple_args(3, 33, 333, 3333)
```
#### [**]をつける場合：辞書型
```python
# 複数のキーワード引数を辞書型として渡す
def func_dictionary_args(**kwargs):
    print(kwargs)

# {'a':3, 'b':33}
func_dictionary_args(a=3, b=33)

# {'c':3, 'b':33, 'd':3333, 'a':333}
func_dictionary_args(c=3, b=33, d=3333, a=333)
```
###リストやタプル型を展開して渡す場合
```python
def func(a, b, c):
    Do some process

# [*]をつけて渡すと、要素が展開されて順に位置引数として渡される
# OK: a=3, b=33, c=333
list = [3, 33, 333]
func(*list)

# NG: 要素数と引数の数が一致していない
list = [3, 33]
func(*list)
```
###辞書型を展開して渡す場合
```python
def func(a, b, c):
    Do some process

# [**]をつけて渡すと、要素のキーが引数名、値が引数の値として展開されて、
# キーワード引数として渡される
# OK: a=3, b=33, c=333
dictionary = {'a': 3, 'b': 33, 'c': 333}
func(**dictionary)

# NG: 引数名と一致するキーが無い or 一致しないキーがある
dictionary = {'a': 3, 'b': 33, 'x': 333}
func(**dictionary)
```
#繰り返し
##for
### 基本形
```python
# for <ループ変数> in <リスト>:
list = ['a', 'b', 'c']
for item in list:  
    print(item) # => a, b, c

# for <ループ変数> in <辞書>:
dictionary = {"a":97, "b":98, "c":99}
for key, val in dictionary.items():
    print(key, val) # => a97, b98, c99

# range：指定した回数
for count in range(5):
    print(count)  # => 0, 1, 2, 3, 4

# range: 初期値と最終値、増分値を指定できる
for count in range(5, 2, -1):
    print(count)  # => 5, 4, 3

# enumerate：indexと要素の取扱い
list = ['a', 'b', 'c']
for index, item in enumerate(list):
    print(index, item)  # => 0a, 1b, 2c

# zip：複数の反復可能オブジェクトの取扱い
list = ['a', 'b', 'c']
unicode_point = [ord(c) for c in list] # 文字をUnicode値に変換[97, 98, 99]
for item, point in zip(list, unicode_point):
    print(f'{item}{point}')  # => a97, b98, c99
```
###`for`と`break`&`continue`
```python
# break：ループの脱出
list = ['a', 'b', 'c']
for item in list:
    if item == 'b':  # item==b なら最も内側のループ脱出
        break
    print(item)  # aを出力後、ループ終了

# ループの継続：continue文
for item in list:
    if item == 'b':  # item==b なら以降の処理を省略してループを継続
        continue
    print(item)  # => a, cのみ出力
```
###`for~else`
```python
list = ['a', 'b', 'c']

# 下記の*1と*2は基本的に同じ処理になるが、for内でbreakが実行された場合に変わってくる。
# breakが実行されるとelseブロック内の処理は実行せずにforが終了。次の処理へ移る

# *1
for item in list:
    some process 
    break
else:
    some process # breakで飛ばされる

# *2
for 変数 in イテラブルオブジェクト:
    some process
    break

some process # breakで飛ばされない
```

##while
```python
# while <条件式>:
num = 0
while num < 2:
    # 条件式が真のときに実行
    print("num = " + str(num))
    num += 1
```
###`while~else`
```python
while <条件式>:
    some process 
    break
else:
    some process # breakで飛ばされる
```
※`for ~ else`と同じ原理。

#条件分岐
##`if`文
```python
# 基本形 if ~ elif(省略可) ~ else(省略可)
num = 1
if num == 0:
    some process
elif num == 1:
    some process
else:
    some process

# 複数条件 and, or
if x <= 5 and y <= 5:
if x in l or y in l:

# 否定条件
if not s:

# リストに特定の要素が含まれているか判定
list = ['toyota', 'nissan', 'honda', 'suzuki', 'daihatsu']
name = 'hino'
if name in list:
    some process

# 文字列に特定の文字列が含まれているか判定
s = 'aaa bbb'
x = 'ccc'
if x in s:  # 'aaa bbb'に'ccc'が含まれるか
    some process
else:
    some process

# リストに特定の要素が含まれているか判定
s = [randint(0, 10) for x in range(5)] # 0~9の長さ5のランダム数値のリスト
x = 7
if x not in s:  
    print('not hit')
else: # リストに7があればここの処理
    print('hit')

# 辞書に特定の要素が含まれているか判定
s = {'a':97, 'b':98, 'c':99, 'd':100, 'e':101}
x = 'b'
if x in s:  # 辞書はキー検索 a, b, c, d, e
    some process

# リストが空かどうかを条件とする ※jsだと[]はtrueになるけど、pythonは違うのか
list = []
if list:
    some process when list has some items
else:
    some process when list has nothing

# 2つのオブジェクトが同一(参照値が同じ)か判定
s1 = 'aaa bbb'
s2 = s1
if s2 is s1:
    some process when two objects are identical
```

##switch
###**※Pythonにswitch文はない。理由として`if~elif~else`で同じことができるから**


#まとめ

一旦、Pythonを読み書きする上で、必要な基本的な知識とその文法をまとめてみました。

switch文が無いというのが驚き。

そして、辞書はJSONだからわかるけど、
タプル型とかいうイミュータブル(変更できない)オブジェクトの概念が出てきたので、
もう少し勉強が必要だと感じましたが、

一旦これで、Pythonのコードとか読めるようになったんじゃないかな！？🤩✨

以上、
ありがとうございました。