知らなかったPython3の言語仕様まとめ

他の言語とちょっと違う・・・・というのを中心に個人用のメモとして残そうと思います

[オライリーの入門 Python 3を参照しています](https://www.amazon.co.jp/dp/4873117380/)
[Python3 公式ドキュメント](https://docs.python.org/3/contents.html)
## データ型

Pythonでは、ブール値、整数、浮動小数点数、文字列、データ構造(※1)、関数、プログラムもすべてオブジェクトとして扱われる

:::note warn
プリミティブ型が存在しないので、全て値の参照を保持する
複製したいときには注意が必要である
:::

|種類|データ型|
|---|---|
|数値型|[int](https://docs.python.org/3/library/stdtypes.html?highlight=int)|
|数値型|[float](https://docs.python.org/3/library/stdtypes.html?highlight=float)|
|複素数型|[complex](https://docs.python.org/3/library/stdtypes.html?highlight=complex)|
|文字列|[string](https://docs.python.org/3/library/string.html?highlight=string#module-string)|
|真偽値|[boolean](https://docs.python.org/3/library/stdtypes.html?highlight=boolean)|

:::note warn
複素数型という型が存在する
:::

:::note warn
各ビルトインオブジェクトには、`__len__()`のような、前後を`__`で囲まれた、予約済みのマジックメソッドが存在する
アンダースコアを利用した命名規則　については、[こちら](https://medium.com/lsc-psd/pythonic%E8%89%B2%E3%80%85-python%E3%81%AE%E3%82%A2%E3%83%B3%E3%83%80%E3%83%BC%E3%82%B9%E3%82%B3%E3%82%A2-%E3%82%92%E4%BD%BF%E3%81%84%E3%81%93%E3%81%AA%E3%81%9D%E3%81%86-3c132842eeef)を参照する
:::

## データ構造
- リスト、タプル、辞書、集合という4種類のデータ構造を作成できる

|データ構造|データ型|ミュータブル|初期化|関数|サンプル|内包表記|
|---|---|---|---|---|---|---|
|リスト|シーケンス|Y|[]|list()|[1,2]|[expression for item in iterable]|
|タプル|シーケンス|N|()|tuple()|("a","b")||
|辞書|辞書|Y|{}|dict()|{"k1":"v1","k2":"v2"}|{key_item: value_item for item in iterable}|
|集合|集合|Y|{}|set()|{"a","b"}|{ite for item in iterable}|

:::note warn
セット型とは別にタプルというのが用意されている
:::

### リスト操作

|データ構造|取り出し|追加|結合|削除|有無|
|---|---|---|---|---|---|
|リスト|`[start:end:step]`|append()<br>insert()|extend()<br>+=|remove()<br>del|in
|タプル|---|---|---|---|---|
|辞書|キーを利用|キーを利用|キーを利用|キーを利用|in|
|集合|---|---|---|---|in|


#### 集合の演算
|タイプ|演算子|関数|サンプル|
|---|:---:|---|:---:|
|積集合|&amp;|intersection()| a & b |
|和集合|&#124;|union()| a &#124; b|
|差集合|-|difference()| a - b |
|排他的OR|^|symmetric_difference()| a ^ b |
|部分集合(サブセット)|<=|issubset()| a <= b |
|上位集合(スーパーセット)|>=|issuperset()| a >= b |

## 関数

### 引数の分解
- `*`を使って、引数のタプル化
```python
def print_args(*args):
```
- `**`使ってキーワード引数の辞書化
```python
def pring_arges(**args)
```

### docstringを使ったコメント付与
```python
def echo(str):
    '文字列を出力する関数です'
    return str
```
```python
def echo(str):
    '''
    文字列を出力する関数です
        1. 文字列型出ない場合には文字列に変換します
    '''
    echo string(str)
```

:::note info
従来はJDOCやRDocなどといった外部モジュールでコメント形式でドキュメントを記載していたが、メソッドの標準仕様になっている
:::

### 高階関数と関数渡し

```python
def echo(str):
    print(str)

def do_something(func,arg1):
    func(arg1)

do_something(echo, "message")

> message
```

### 関数内関数とクロージャー
```python
def outer(str)
    def innter():
        return "%s" % str
    return inner()
```

:::note warn
外側の関数に渡されたstrという変数のスコープは内側の関数から見えている状態
:::

### ラムダ関数

```python
muliply_6 = lambda i: i * 6
print(muliply_6(10))
```

:::note info
`lambda`を使った無名関数はRubyでも馴染みの深い仕様
:::

### ジェネレーター
```python
def get_default_value_list(length, default_value):
    for x in range(0, length):
        yield default_value
    
print(get_default_value_list(12, 0))

> <generator object get_default_value_list at 0x10c55a1b0>
```

:::note info
`yield`を使った無名関数はRubyでも馴染みの深い仕様
Pythonではすべてがオブジェクトとして扱われるので、コピーなどで活用の機会が多そう
:::

### デコレーター
```python
def unvail(func):
    def new_function(*args, **kwargs):
        print("FuncName:", func.__name__)
        print("Arguments: ", args)
        print("Keyword Arguments:", kwargs) 
        return func(*args, **kwargs)
    return new_function

@unvail
def test(str, p1=0):
    print(str, p1)

test("test", p1=2)
```

:::note info
`@`を使ったデコレーターはJava界隈(javax/spring)やTypeScriptなどで見たことがあります
:::

### 関数内再代入の禁止
```python
animal = 'cat'

def change_and_print_global():
    animal = 'dog'
    print(animal)

def change_and_print_global2():
    global animal
    animal = 'bird'
    print(animal)
```

animal => change_and_print_global() => animalの実行結果は、cat,dog,cat
animal => change_and_print_global2() => animalの実行結果は、cat bird bird

:::note warn
関数内からローカル変数ではなく、グローバル変数にアクセスしようとする場合には、`global`キーワードを利用しないといけません
PHPが同じ仕様でしたので馴染みがあります
:::

:::note info
変数の一覧を取得するには、ローカル変数の場合は`locals()`、グローバル変数の場合には`globals()`
:::