すぐ忘れるPythonメモ

## ググり方

`python docs 調べたいこと` でググると[公式ドキュメント](https://docs.python.org/ja/3/)にたどり着きやすい。

# 基本

paiza スキルチェックのDランクで戦えるくらいのレベル。

## 入出力
### `stdout`へ値を出力

https://docs.python.org/ja/3/library/functions.html#print

```py
# 数値の場合
print(123)

# 文字列の場合
print("thanks")
```

- 文字列以外のオブジェクトも文字列に変換される
- 最後に改行される

### `stdin`から文字列を1行取得

https://docs.python.org/ja/3/library/functions.html#input

```py
s = input()
```

- 末尾の改行は取り除かれる

## 基本の型

https://docs.python.org/ja/3/tutorial/introduction.html#numbers
https://docs.python.org/ja/3/tutorial/datastructures.html#tuples-and-sequences

```py

n = 123   # 整数
f = 123.4 # 小数

s1 = 'もじれつ' # string (シングルクォートで指定する場合)
s2 = "もじれつ" # string (ダブルクォートで指定する場合)

ln = [1, 2, 3]  # リスト
lx = [1, "two"] # 異なる型の混在も可能

d = { "a": 1, "b": 2, "c": 3 } # 辞書型(俗にHashとかMapとかDictと呼ばれるモノ)

t = (1, "two") # タプル(Tuple)

# 真偽値
b1 = True
b2 = False

# null とか nil っぽいモノ
null = None
```

- 文字列はシングルクォートでもダブルクォートでも、どちらを使ってもいい
- 辞書のキーを`{ "a": 1 }`ではなく、クォート無しで`{ a: 1 }`とやると、変数aの値をキーにしようとするので注意
- タプルの要素へのアクセスは、リストと同様に`t[0]`でアクセスできる

## 型変換

### 文字列を整数に変換

https://docs.python.org/ja/3/library/functions.html#int

```py
i = int("123")
```

### オブジェクトを文字列に変換

https://docs.python.org/ja/3/library/functions.html#func-str

```py
s = str(123)
```

## 条件分岐

### if文
https://docs.python.org/ja/3/tutorial/controlflow.html#if-statements

```py
name = input()

if name == "あんちゃん":
  print("尊いマジしんどいこれは推せるフォーエバー……")
elif name == "みーちゃん":
  print("薄っぺらすぎ")
else:
  print("めっちゃやむ……！") 
```

- `if ...`、`elif ...`、`else` の各行の後に `:` をつけないとエラーになる
- ブロックは`{ }`などで囲うのではなく、スペースでインデントする
- `elif`と`else`部分は省略できる
- `elif`部分は複数書ける
- `else if`や`elsif`ではなく、`elif`なので注意
- Pythonは`if式`ではなく`if文`なので、条件分岐の結果を変数に直接代入などは(`if式`な言語とは違い)出来ない

## ループ

### for文

https://docs.python.org/ja/3/tutorial/controlflow.html#for-statements

```py
ns = [1, 2, 3]

for n in ns:
  print(n)
```
- `for ... in ...`の後に`:`をつけないとエラーになる
- ブロックは`{ }`などで囲うのではなく、スペースでインデントする


## 文字列処理

### 文字列をスペースで分割してリストにする

https://docs.python.org/ja/3/library/stdtypes.html#str.split

```py
source = "ペコリーヌ コッコロ キャル シェフィ"

names = source.split()
```

<!-- ============================================ -->

# 初級

## 関数

### 定義

```py
def f(a, b, c):
  return a + b + c
```

- `def`の後に関数名、引数リスト、`:`
- `return`を書かないと戻り値にならない
- ブロックは、スペースでインデントする
- 文は複数書ける

### sqrt
```py
import math

x = math.sqrt(2)
```

## テキスト処理
### `stdin`を改行で分割して「文字列のリスト」にする

```py
import sys

ts = sys.stdin.read().splitlines()
```

- `sys`モジュールを`import`しないとダメっぽい

### 「文字列のリスト」を「整数のリスト」にする

```py
# map関数を使う場合
ns = list(map(int, ["1", "2", "3"]))

# リスト内包表記を使う場合
ns = [
    int(x)
    for x in ["1", "2", "3"]
]
```

### 「整数のリスト」を「文字列のリスト」にする

```py
# map関数を使う場合
ss = list(map(str, [1, 2, 3]))

# リスト内包表記を使う場合
ss = [
    str(x)
    for x in [1, 2, 3]
]


```


## リスト処理

### `range`を`list`にする

```py
ns = list(range(10))
```

- `list`関数でリストっぽいモノなら変換できるみたい

### 数値の合計

```py
s = sum([1, 2, 3, 4, 5])
```

<!-- ============================================ -->
# 中級

## Functional

### lambda式(ラムダ式)

```py
# 引数2個の場合
plus = lambda a, b: a + b

# 引数1個の場合
plus1 = lambda a: plus(1, a)

# 引数0個の場合
hello = lambda: print("hello")
```

- `return`は書かなくても戻り値を返してくれる
- 複数行は書けないみたい

### unique

```py
ns = list(set([1, 2, 2, 3]))
```

- `set`型にして重複を除いてから`list`に再変換するらしい

### filter
```py
# 例えば偶数でフィルターする場合
even = lambda n: n % 2 == 0

# filter関数を使う場合
ns = filter(even, range(10))

# リスト内包表記の場合
ns = [
    x
    for x in range(10)
    if even(x)
]
```

### concat, flatten
```py
ns = sum([[1,2,3], [10, 20, 30]], [])
```

- `sum`関数の第2引数に初期値を指定することで、`+`を使った`fold`や`reduce`っぽくなるみたい

### map

```py
# 例えば、それぞれの要素に1を足す場合
plus1 = lambda n: n + 1

# map関数を使う場合
ns = list(map(plus1, [1, 2, 10, 20, 100, 200]))

# リスト内包表記の場合
ns = [
    plus1(x)
    for x in [1, 2, 10, 20, 100, 200]
]
```

### reduce
```py
from functools import reduce

ns = [1, 2, 3, 4, 5]

# オレオレsum
plus = lambda a, b: a + b
my_sum = reduce(plus, ns, 0)

# オレオレproduct
times = lambda a, b: a * b
my_product = reduce(times, ns, 1)

# オレオレlen
one = lambda _: 1
my_len = reduce(plus, map(one, ns), 0)
```

- `functools`モジュールから`reduce`をインポートする

## Class

### (たぶん)最小のクラス定義
```py
# 空のクラス
class Hoge:
    pass
```

### インスタンス化

```py
hoge = Hoge()
```

- 他の言語だと `new` みたいなもの

### フィールドの設定 🐛
```py
hoge = Hoge()
hoge.x = 1
hoge.y = 2
```

- あとから好きなフィールドを追加しても平気 🐛
    - 例外とかぶん投げてこない

### メソッドの定義

```py
class Hoge:
    def plus1(self, x):
        self.last_x = x  # インスタンスの状態更新 🐛 
        return x + 1

hoge = Hoge()
y = hoge.plus1(10)

print(y)
print(hoge.last_x)
```

- クラス定義内に関数を定義するように書く
- 第一引数に自分自身を参照するための `self` を書く
    - 本当は `self` じゃなくても、変数名として使えるなら何でもいいらしい

### コンストラクタ

```py

class User:
    def __init__(self, name):
        self.name = name

    def say_name(self):
        print("我が名は" + self.name + "！")

user = User("ATM")

user.say_name()
```

- `__init__` を定義するとコンストラクタになる