【Python】1つでも新しい発見があったらいいねください

本記事では、Pythonの豆知識？を10個ご紹介します。
1つでも新しい発見があれば嬉しい限りです。（なかったらすみません。。。）

それではどうぞ！

## enumerateでxからカウント
`enumerate`は要素のインデックスと要素を同時に取り出すことができる便利な関数ですが、

~~~py:In
color_list = ["red", "yellow", "blue"]

for i, color in enumerate(color_list):
    print(i, color)
~~~
~~~:Out
0 red
1 yellow
2 blue
~~~

enumerate(A, x)でカウントをxから始められます。

~~~py:In
color_list = ["red", "yellow", "blue"]

for i, color in enumerate(color_list, 5):
    print(i, color)
~~~
~~~:Out
5 red
6 yellow
7 blue
~~~


## f-stringでデバッグ
f-stringで

print(f'{ans=}')

と書くと

ans=○○

と変数名ごと出力されます。デバッグに便利です。

~~~py:In
year = 2023
place = 'Tokyo'
print(f'{year=}, {place=}')
~~~
~~~:Out
year=2023, place='Tokyo'
~~~

## コピーの生成
`[:]`でコピー、`[::-1]`で逆順のコピーを生成できます。

~~~py:In
l1 = [1, 2, 3, 4]
l2 = l1[:]
l3 = l1[::-1]
print(l1)
print(l2)
print(l3)
~~~
~~~:Out
[1, 2, 3, 4]
[1, 2, 3, 4]
[4, 3, 2, 1]
~~~

## raw文字列の注意点

文字列の先頭にｒまたはＲをつけることでエスケープシーケンスを無効化することができますが、

~~~py:In
path = "C:\windows\name\desktop\sample.txt"
print(path)
~~~
~~~:Out
C:\windows
ame\desktop\sample.txt
~~~

~~~py:In
path = r"C:\windows\name\desktop\sample.txt"
print(path)
~~~
~~~:Out
C:\windows\name\desktop\sample.txt
~~~

raw文字列は末尾が奇数個のバックスラッシュで終わるとエラーになるので注意。

~~~py:In
path = r"C:\windows\name\desktop\"
~~~
~~~:Out
SyntaxError: unterminated string literal (detected at line 1)
~~~

## 安定ソート
sorted関数はイテラブルの要素を並べ替えた新たなリストを返しますが、

~~~py:In
print(sorted([5, 2, 3, 1, 4]))
~~~
~~~:Out
[1, 2, 3, 4, 5]
~~~

sortedは安定(Stable)です。

<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2638073/2de2ef2c-f180-410f-aa6c-566c4e996028.png width=80%>


~~~py:In
data = [('red', 1), ('blue', 1), ('red', 2), ('blue', 2)]

print(sorted(data, key=lambda d: d[0]))
~~~
~~~:Out
[('blue', 1), ('blue', 2), ('red', 1), ('red', 2)]
~~~

## 辞書の結合

辞書の結合は`｜`演算子で結合できます。

~~~py:In
d1 = {'k1': 1, 'k2': 2}
d2 = {'k3': 3, 'k4': 4}

d = d1 | d2
print(d)

d3 = {'k5': 5, 'k6': 6}

d = d1 | d2 | d3
print(d)
~~~
~~~:Out
{'k1': 1, 'k2': 2, 'k3': 3, 'k4': 4}
{'k1': 1, 'k2': 2, 'k3': 3, 'k4': 4, 'k5': 5, 'k6': 6}
~~~

::: message alert
重複するキーがある場合は右側の値で上書きされます。
:::

~~~py:In
d1 = {'k1': 1, 'k2': 2}
d2 = {'k1': 10, 'k3': 3, 'k4': 4}

d = d1 | d2
print(d)
~~~
~~~:Out
{'k1': 10, 'k2': 2, 'k3': 3, 'k4': 4}
~~~

## 要素数の異なるzip
zip関数は要素数が異なる場合、多い分は無視されますが、

~~~py:In
num_list = [1, 2] 
value_list = ['A']

zipped = list(zip(num_list, value_list)) 
print(zipped)
~~~
~~~:Out
[(1, 'A')]
~~~

`strict=True`にすると、引数の要素数が異なる場合、ValueErrorが発生します。

~~~py:In
num_list = [1, 2]
value_list = ['A']

zipped = list(zip(num_list, value_list, strict=True)) 
print(zipped)
~~~
~~~:Out
ValueError: zip() argument 2 is shorter than argument 1
~~~

## 引数を位置専用引数に

`/`を使うと引数を位置専用引数にできます。位置専用引数は`/`より前に置かれます。

~~~py:In
def pos_only(arg, /):
     print(arg)

pos_only(2)
pos_only(arg = 5)
~~~
~~~:Out
2
TypeError: pos_only() got some positional-only arguments passed as keyword arguments: 'arg'
~~~

位置専用引数を活用することで、位置引数と任意個数のキーワード引数の衝突を防げます。

~~~py:In
def func(a, **word):
     print(a)
     print(word)

func(0, a = 1, b = 2, c = 3)
~~~
~~~:Out
TypeError: func() got multiple values for argument 'a'
~~~
~~~py:In
def func(a, /, **word):
     print(a)
     print(word)

func(0, a = 1, b = 2, c = 3)
~~~
~~~:Out
0
{'a': 1, 'b': 2, 'c': 3}
~~~

## セイウチ演算子
python3.8からセイウチ演算子`:=`が使えるようになりました。
コードをスッキリ書くことができて、取得したデータに対して分岐させるときなどに便利です。

~~~py:In
s = 'python'
n = len(s)

if n > 5:
    print(str(n) + "文字でした。5文字より多いです。")
else:
    print(str(n) +"文字でした。5文字以下です。")
~~~
~~~:Out    
6文字でした。5文字より多いです。
~~~
~~~py:In
s = 'python'

if (n := len(s)) > 5:
    print(str(n) + "文字でした。5文字より多いです。")
else:
    print(str(n) +"文字でした。5文字以下です。")
~~~
~~~:Out
6文字でした。5文字より多いです。
~~~

## match文

python3.10からの新機能として、match文が導入されました。match文を使った方がif文よりスッキリ書ける場合があります。

~~~py:In
error_code = 400

match error_code:
    case 400:
        print("Bad request")
    case 404:
        print("Not found")
    case 418:
        print("I'm a teapot")
    case _:
        print("Something's wrong with the internet")
~~~
~~~:Out        
Bad request
~~~
~~~py:In
error_code = 400

if error_code == 400:
     print("Bad request")
elif error_code == 404:
    print("Not found")
elif error_code == 418:
    print("I'm a teapot")
else:
    print("Something's wrong with the internet")
~~~
~~~:Out
Bad request
~~~

最後のブロック_はワイルドカードの働きをし、マッチに絶対失敗しません。また、マッチするケースがない場合、そのブロックは実行されません。

## おわり
最後までお読みいただきありがとうございました！
新しい発見はありましたでしょうか。

zennで書籍を書いています。
良ろしければPythonの学習にご活用ください。

https://zenn.dev/python_academia/books/eabcc6b22afff5

https://zenn.dev/python_academia/books/f1c725e023dcae