python3 思い出しメモ

# 本記事について
私自身がpython3について思い出したり、基本構文を参考にするためのメモです。

# おまじない
```python:おまじない
# coding: utf-8
```

# コメントアウト
```python:コメントアウト
# コメントアウトできます

'''
複数行のコメントアウトが可能
複数行のコメントアウトが可能
'''
```

# print
```python:print
# 数値
print(数値)

# 文字列
print("文字列")

# 改行しない
print(xxx, end="")

# 改行
print()

#**********************************  f文字  **********************************
# 参考サイト：https://note.nkmk.me/python-f-strings/
# 記述方法　「123 and abc」と表示
# 「""」「''」どちらでもOK
num = 123
word = 'abc'

1. print('{} and {}'.format(a, b))
2. print('{first} and {second}'.format(first=a, second=b))
3. print(f'{a} and {b}')

# ゼロ埋め 「00001234」と表示
num = 1234
1. print(f'{num:08}')
2. print('{:08}'.format(num))

#*****************  ２次元配列の中身をそのまま表示  *****************
## 例:list = [[0,1,2,3],[1,2,3,4],[2,3,4,5]]
#### 0123
#### 1234
#### 2345
for i in list:
    print(*i, sep="")
#    print(*i, sep=",") #sep=","とすると「,」区切りになる
```

# 変数
```python:変数
num = 10
word = "文字列"

# データ型を明示
num :int = 10
word :string = "文字列"

# 長さ
lenght :int= len(variable)

#*****************************  置換  *****************************
文字列.replace('置換対象の文字列', '置換後の文字列')

#***************** 文字列から特定の位置を取得 ※頭の文字は「0」*****************
word = "Hello, World!"
word[5]      => ,
word[1:4]    => ell
word[:4]     => Hell
word[6:]     => orld!
word[:]      => Hello, World!
# 負の数で後ろから　※一番後ろは「-1」
word[-5]     => o
word[-4:-1]  => rld
```

# データ型の判断
```python:データ型の判断
# 文字列が整数かどうか
文字列.isdigit()
## 1, 100, 11000 => True
## -10, 1.33, "alte" => False

```

# メソッド（関数）
```python:メソッド（関数）
# 関数定義 ※頭文字は小文字がスタンダード
def func_name():
    関数処理

# 関数の呼び出し
func_name()

#アノテーション（->）
#アノテーション：引数のデータ型を明示的にする
def func_name() -> 返り値の型名:

#*****************  引数のデフォルト  *****************
## 例：argument2のデフォルトがtest
def func_name(argument1 = "test1", argument2 = "test2"):
func_name(argument2 = "testX") # argument2のみ指定

#*************** 可変長引数（リスト）=引数がリストとして長さが変化する ***************
## 例：argument2が可変長引数（リスト）
def func_name(argument1, *argument2):
func_name("test1", "list1", "list2", "list3")

#*****************  可変長引数（辞書）=引数が辞書として長さが変化する  *****************
## 例：argumentが可変長引数（辞書）
def func_name(**argument):
func_name(name="名前", age=24, tall=175, hoby="映画")
```

# クラス（class）
```python:
#*****************  クラスの定義 ※頭文字は大文字  *****************
# クラス内の関数の引数に「self」を必ず入れる =>オブジェクトの情報を持つために必要
class ClassName:
    variable = xx  # クラス変数 = クラス内でのみ使用する変数
    def func_name(self, argument):
        関数処理

#*****************  クラスからオブジェクト（インスタンス）を作成する  *****************
# オブジェクト = 変数とメソッドをセットにした塊
object1 = ClassName()
object1.func_name("argument1")

#**************************  コンストラクタ  ***************************
# コンストラクタ = 初期実行 => 「__init__」メソッド
## self.*** = インスタンス変数  =>オブジェクトごとに持つインスタンス変数
class ClassName:
    def __init__(self, argument):
        self.argument = argument
    def func_name(self):
        print(self.argument)

object1 = ClassName("argument1")
object1.func_name()
object1.argument  # クラス変数の呼び出し


#********************************** 継承  **********************************
## 例
## 親クラス（スーパークラス）= ParentClassName
## 子クラス（サブクラス）= ChildClassName
class ParentClassName:
    def __init__(self, argument):
        self.argument = argument
    def parent_func_name(self):
class ChildClassName(ParentClassName):  # 子クラスの引数に親クラス名を入れる
    def child_func_name(self):

object = ChildClassName("argument")
object.child_func_name()
object.parent_func_name()   #親クラスのメソッドも呼び出せる（クラス変数も維持）

#***************** クラス内の他のメソッドを実行  *****************
## クラス内から他のメソッドを実行=「self.method()」
class ParentClassName:
    def parent_func_name(self):
        self.__naibu()
    def __naibu(self):

#*****************  子クラスで親クラスのメソッドを実行  *****************
## 親クラスのメソッドを実行=「super().method()」
class ChildClassName(ParentClassName):
    def __init__(self):
        super().__init__("argumentX")


#*****************  プライベートメソッド（関数）  *****************
## func_nameメソッドをプライベートメソッドにする = メソッド名の頭文字に「__」を付ける
## 外から呼び出し不可になる = クラス内でのみ使用するメソッド
class ClassName:
    def __init__(self, argument):
        self.argument = argument
    def __func_name(self):
        print(self.argument)


#*****************  プライベート変数・プライベートプロパティ  *****************
## argument変数をプライベート変数にする = 変数名の頭文字に「__」を付ける
class ClassName:
    def __init__(self, argument):
        self.__argument = argument


#**************************  クラス変数  ***************************
## クラス変数： クラス自体が維持する変数 = オブジェクト生成されるたびに変数自体は維持される
### 例：クラス変数「__classvariable_count」はオブジェクト生成ごとに「+1」されていく
### ※クラス変数は、外部からいじられないようにプライベート変数（頭に__）に普通はする
class ClassName:
    __classvariable_count = 0
    def __init__(self, argument):
        __classvariable_count += 1


#****************************  クラスメソッド  ****************************
# クラスメソッド：オブジェクトからではなく、クラスから直接呼び出せる
# メソッドとクラスメソッドの呼び出しの違いの例　↓
## メソッドの呼び出し => 1.object1 = ClassName("argument1") 2.object1.summary()
## クラスメソッドの呼び出し => 1.ClassName.summary()
class ParentClassName:
    @classmethod
    def summary(cls, argument):   # 引数に「cls」を必ずつける
```

# 標準入力
```python:標準入力
# 文字の入力
word = input()

# 数値の入力
word = int(input())

# inputだと時間がかかるため、sys.stdinで高速に処理
import sys
for word in sys.stdin: print(word)

# 一行に複数の文字列を入力　=>　リスト化
# 入力値：amazon Microsoft Google
list = input().rstrip().split(" ")
## 配列ごと２次元配列に格納する
list.append(input().rstrip().split(" "))

# 一行に複数の数値を入力　=>　リスト化
## 入力値：23,55,333
list = [int(x) for x in input().rstrip().split(",")]
## 配列ごと数値で２次元配列に格納する
list.append([int(x) for x in input().rstrip().split(" ")])

# ２次元配列の入力　=> リスト化
## 入力値　/　配列
## 1 2 3　/　[[1,2,3],
## 4 5 6　/　[4,5,6],
## 7 8 9　/　[7,8,9]]
list = [input().split() for i in range(行数)] 

# 不特定の行数の入力を配列に格納する
## 入力値
## My name is Mark.
## I am seven years old.
## Nice to meet you.
from sys import stdin
for line in stdin:
  list = line.rstrip().split(' ')
```

# 繰り返し
```python:繰り返し
#***********************  for文  ***********************
# 大前提
for 変数 in 条件:
  処理内容

## 内包表記
[処理内容 for 変数 in 条件]
### 例：[i + j for i in range(10) for j in range(15)]

## 多重内包表記
[[処理内容 for 変数 in 条件] for 変数 in　条件]
###　例：list = [["0" for i in range(10)] for j in range(10)]

## 内包表記 + if文
[ifを満たしたときの内容 if if条件 else ifを満たさないときの内容 for 変数 in for条件]
### 例：list = ["even" if i % 2 == 0 else "add" for i in range(10)]

# x回繰り返す　※最初はi=0になる
for i in range(x):

# 多重forを一つにする
import itertools
for i, j in itertools.product(range(x), range(y)):

# 数値x-yまで増加させて繰り返す
for i in range(x,y):
for i in range(x,y,-1): # x > yで一ずつ減らしていく

# リスト(list)の要素を格納して繰り返す
for i in list:

#***********************  while文  *************************
while 条件式:
    条件式が真の時に実行する文
```
# 配列（リスト）
```python:リスト（配列）
# 定義
init_list = []
list = ["リスト1", "リスト2", "リスト3"]

#***********************  要素内容を取得  ***********************
x = list[列番号]

# ２次元配列
list_2 = [[1, 2, 3], [10, 20, 30], [100, 200, 300]]
x = list_2[行番号][列番号]

##複数を同時に変数に代入
x, y, z = list_2[行番号]


#***********************  入力値＝＞リスト化  ***********************
# 入力値：amazon Microsoft Google
word = input().rstrip().split(" ")

#***********************  一行に複数の数値を入力＝＞リスト化  ***********************
# 入力値：23,55,333
list = [int(x) for x in input().rstrip().split(",")]

#***********************  文字列を一文字＝＞リスト化  ***********************
word = "ABCDEFG"
word_list = list(word)

#*********************** リストに追加  ***********************
# リストの末尾に追加
list.append("文字列")
list.append(数値)

# リストの特定部分に追加
list.insert(配列番号, "文字列")
## list.insert(0, "XXX")  #先頭に追加

#*********************** リストから削除  ***********************
## 特定の要素番号から削除
list.pop(配列番号)
### print(list.pop(0))  >> 「リスト1」が表示 + list[0]が削除

## 特定の要素内容から削除
del list(数値)

# ***********************  リストで検索  ***********************
# リスト要素を検索
検索値 in list
# 戻り値はTrue or False
## 例："リスト3" in list

# リスト要素の数を検索
list.count(検索値)

# リスト要素のindexを検索
list.index(検索値)
## ※検索値を複数持つリストの場合、一番小さいindexが取得可能

# 数値のリストから最大の要素を取得
max(list)

# 数値のリストから最小の要素を取得
min(list)

#*********************** リスト要素数に応じて繰り返す  ***********************
for item in list:
  print(item)

#***********************  ソート  ***********************
# 普通のソート
print(sorted(list))
# 逆ソート
print(sorted(list, reverse=True))

#*********************** 配列の要素を要素番号を使用する：enumerate  ***********************
## 例：list = ["apple", "Gooogle", "Microsoft"]
#### 0 apple
#### 1 Google
#### 2 Microsoft
for i, name in enumerate(list):
    print(i, name)
```

# 辞書
```python:辞書 
# 定義
dictionary = {"キー1":"バリュー1(文字列)", "キー2":バリュー2(数値)}

# 辞書全部表示
print(dictionary)

# キーから特定バリューを表示
label="キー1"
print(dictionary[label])

# 辞書内容の更新
dictionary["キー2"] = バリュー2.1

# 辞書内容の削除
del dictonary["キー2"]

# for文との組み合わせ
for key in dictionary:
	print(dictionary[key] + "です。")
for (key, value) in enemies.items():
	print(key+ "の" + value+ "です。")

# ソート
print(sorted(dictionary )) # キーのみがリスト形式になってソートされる
print(sorted(dictionary .items())) # タプルになる。キーでソートされ、バリューもともに表示可能
#※タプル＝内容の更新不可
```

# 例外処理
```python:例外処理
#********************  例外処理フォーマット  **********************
try:
    実行する内容
except:
    エラーの際に実行する内容
finally:
    例外処理後に必ず実行する内容

#********************  エラーメッセージを表示する  **********************
# 標準出力に表示する
import traceback
except:
    print(traceback.format_exc())

# 標準エラー出力に表示する
import traceback, sys
except:
    sys.stderr.write(traceback.format_exc())

#********************  意図的に例外（エラー）を発生させる  **********************
try:
    raise BaseException("意図的な例外")
```

# 標準ライブラリ
## math
```python:math
import math
# log
math.log(x)
math.log(x, y)

# floor：小数点以下を切り捨て
math.floor(x)

# ceil：小数点以下を切り上げ
math.ceil(x)

# sqrt：平方根=√
math.sqrt(x)

# fabs：絶対値（正にする）
math.fabs(x)

# exp：eのx乗
math.exp(x)

# pow：xのy乗
math.pow(x, y)
=> 組み込み関数 pow(x, y)のほうがいい
```
## datetime
datetimeモジュールで使用可能な4つのオブジェト
* `datetime.datetime` &nbsp;&nbsp;: 日時（日付と時刻）
* `datetime.date`&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: 日付
* `datetime.time`&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: 時刻
* `datetime.timedelta` : 時間差・経過時間。datetimeオブジェクト同士を引き算すると取得できる。

メソッド２つ
* `strftime()` : 日付、時間 → 文字列への変換
* `strptime()` : 文字列 → 日付、時間への変換

参考サイト：https://note.nkmk.me/python-datetime-usage/
```python:datetime オブジェクト
import datetime

#*******************  datetimeオブジェクト（.datetime）  *******************
## 現在の日時（.now()）
dt_now = datetime.datetime.now()
## 属性　year, month, day, hour, minute, second, microsecond
dt_now.year

## 任意の日時作成　↓コンストラクタ
datetime(year, month, day, hour=0, minute=0, second=0, microsecond=0, tzinfo=None)
datetime.datetime(2021, 2, 1)

## dateオブジェトに変更
dt_now.date()

#*********************  dateオブジェクト（.date）  *********************
## 今日の日付（.today()）
d_today = datetime.date.today()
## 属性　year, month, day
d_today.year

## 任意の日付作成　↓コンストラクタ
date(year, month, day)
datetime.date(2021, 2, 1)

#***********************  timeオブジェクト（.time）  ***********************
## 任意の時刻作成　↓コンストラクタ
time(hour=0, minute=0, second=0, microsecond=0, tzinfo=None)
datetime.time(12, 15, 30, 2000)
## 属性　hour, minute, second, microsecond
t = datetime.time(12, 15, 30, 2000)
t.hour

#***********************  timedeltaオブジェクト（.timedelta）***********************
## 属性　days, seconds, microseconds
dt_now = datetime.datetime.now()
dt = datetime.datetime(2018, 2, 1, 12, 15, 30, 2000)
td = dt_now - dt

## 任意の時間差分を作成　↓コンストラクタ
timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0)
td_1w = datetime.timedelta(weeks=1)  # 一週間

## timedeltaオブジェクトを使った引き算、足し算
### 例：１週間後を取得
datetime.date.today() + datetime.timedelta(weeks=1)
```
```python:datetime メソッド
#*******************  strftime(): 日付、時間 → 文字列への変換  *******************
## datetimeオブジェクトとdateオブジェクトのメソッド
dt_now = datetime.datetime.now()
dt_now.strftime('%Y-%m-%d %H:%M:%S')

#*******************  strptime() : 文字列 → 日付、時間への変換  *******************
## datetimeオブジェクトのメソッド
date_str = '2021/2/1 12:30'
date_dt = datetime.datetime.strptime(date_str, '%Y/%m/%d %H:%M')
```
## sys
Pythonのインタプリタや実行環境に関する情報を扱うことが可能になる
```python:sys
import sys

# 引数の使用
sys.argv[数値]
## 例：# sys.py hoge XXX
[print(sys.argv[x]) for x in range(len(sys.argv))]
### x=0 => sys.py / x=1 => hoge / x=2 => XXX

# 標準入力を高速にする
## input()だと時間がかかる
for word in sys.stdin:
    # lines.append(word.rstrip('\r\n'))
    # print(word)

# プログラム終了
sys.exit()
```
## os 
ファイル操作やコマンドラインでのシステム操作が可能
```python:os
import os

# ファイルまたはディレクトリが存在するか判定
os.path.exists("パス")
## あればTrue、なければFaulse

# ファイルを開く
file = opne('パス', 'オプション')
## 【オプション】w:新規作成 a:上書き(なければ作成)

# ファイルへの書き込み（write）
file.write('書き込む内容\n')

## 配列を一括でファイルに書きこむ（writelines）
list = ['list1\n', 'list2\n', 'list3\n']
file.writelines(list)

# ファイルを閉じる
file.close()
```

## numpy
```python:numpy
import numpy as np

# 配列の定義
arr = np.array([1,2,3,4])
arr = np.array([x**2 for x in range(5)])

# 連続する同じ数値をグループ化する
arr = [0, 0, 0, 1, 1, 2, 0, 0]
print([(k, list(g)) for k, g in itertools.groupby(arr)])
## 出力結果： [(0, [0, 0, 0]), (1, [1, 1]), (2, [2]), (0, [0, 0])]

# 二次元配列全体で最大値の座標を取得（複数ある場合は最初の一つ）
arr = np.array([[1,2,3,4],[3,5,2,3],[1,2,5,3]])
idx = np.unravel_index(np.argmax(arr), arr.shape)
## print(idx) => (2, 1)
```
## itertools
```python:itertools
import itertools

# 連続する同じ数値をグループ化する
arr = [0, 0, 0, 1, 1, 2, 0, 0]
print([(k, list(g)) for k, g in itertools.groupby(arr)])
## 出力結果： [(0, [0, 0, 0]), (1, [1, 1]), (2, [2]), (0, [0, 0])]
```
# その他
## ランレングス圧縮
`aaaabbcccddd`の文字列を圧縮して`a4b2c3d3`とする。
下のコードでは配列表示されるようにしている。
LeetCode：https://leetcode.com/submissions/detail/742835849/
```python:ランレングス圧縮（Run length encoding; 連長圧縮）
def rle(s):
    tmp, count, ans = s[0], 1, []
    for i in range(1,len(s)):
        if tmp == s[i]:
            count += 1
        else:
            ans.append([tmp,count])
            tmp = s[i]
            count = 1
    ans.append([tmp,count])
    return ans

word = "aaaabbcccddd"
print(rle(word))
>> [['a', 4], ['b', 2], ['c', 3], ['d', 3]]

# ※戻り値をa4b2c3d3をしたい場合は関数を以下部分で変更する
## ans = ""
## ans += tmp+str(count)
```
## Manacherのアルゴリズム
極大回文を求めるアルゴリズムです。
文字列の各文字を中心とした回文の最長半径を求める。
一文字でも回分とみなすため、最小半径は１である
（例）`aabbcccbbaa`の場合は、`[1, 1, 1, 1, 1, 6, 1, 1, 1, 1, 1]`である。
LeetCode：https://leetcode.com/submissions/detail/744399492/

```python:Manacherのアルゴリズム
s = "aabbcccbbaa"

'''偶数の場合は文字列の間に「#」を入れて考える必要がある（"a#a#b#b#c#c#c#b#b#a#a"）
if len(s) % 2 == 0:
    s_len = len(s)
    for n in range(s_len):
        if n < s_len-1:
            s = s[:2*n+1] + "#" + s[2*n+1:]
'''
i, j = 0, 0
r = [ 0 for x in range(len(s)) ]  # 極大回文の半径リスト 
while i < len(s):
    while i - j >= 0 and i + j < len(s) and s[i-j] == s[i+j]:    
        j += 1
    r[i] = j
    k = 1
    while i - k >= 0 and k + r[i-k] < j:
        r[i+k] = r[i-k]
        k += 1
    i += k
    j -= k

print(r)
```
## deque（デキュー）
≒　リスト形式で先頭・末尾についての操作のみをすることが可能です。
途中の部分を探したり、処理をするとリストより時間がかかってしまう
https://note.nkmk.me/python-collections-deque/

```python:deque
#****************  deque作成 deque([list1, list2])  ****************
deque_test = deque([1,2,3,4,5])

#***********************  要素の取得  ***********************
print(deque_test [0])
>> 1
## マイナスで末尾からの数も可

#***********************  要素の追加  ***********************
## 末尾に追加
deque_test.append(6)   # deque([1,2,3,4,5,6])

## 先頭に追加
deque_test.appendleft(6)   # deque([6,1,2,3,4,5])

## 末尾に複数要素追加
deque_test.extend([6,7])   # deque([1,2,3,4,5,6,7])

## 先頭に複数要素追加
deque_test.extendleft([6,7])   # deque([7,6,1,2,3,4,5])

## 中間に要素追加
deque_testinsert(3, 'XXX')   # deque([1,2,3,'XXX'4,5])

#***********************  要素の削除  ***********************
## 末尾に削除
deque_test.pop()   # deque([1,2,3,4])

## 先頭に削除
deque_test.popleft()   # deque([2,3,4,5])

## 特定の要素削除
deque_test.remove(2)   # deque([1,3,4,5])

## 全要素削除
deque_test.remove()   # deque([])

#***********************  要素のローテート  ***********************
# 末尾を先頭にローテート
deque_test.rotate()   # deque([5,1,2,3,4])
## .rotate(x)   => xの数だけローテートすることが可能

# 先頭を末尾にローテート
deque_test.rotate(-x)   # deque([2,3,4,5,1])
## .rotate(-x)   => xの数だけローテートすることが可能
```
# 参考リンク
https://note.nkmk.me/