知っていると便利！Pythonテクニック7選

# はじめに
開発やコードレビューをしていく中で、これが使えるとコードがシンプルになって嬉しいなと思ったPythonの文法や仕様をまとめてみました。
主に、Pythonは一通り書けるようになって次にレベルアップしたいと思っている方を対象としています。


# 1. f-string
対応：Python3.6〜

f-stringは、'f'や'F'が先頭に付いた文字列で、正式には「フォーマット済み文字列リテラル」と呼ばれます。
特徴としては、中に変数や式を埋め込むことができます。
```Python
a = 12.345
print(f"value: {a}")  # `"value" + str(a)`より簡単に書ける
# value: 12.345

print(f"value: {a * 10}")  # 式も埋め込める
# value: 123.45
```
また、フォーマットを指定することもできます。
```Python
print(f"value: {a:.2f}")
# value: 12.35
```
その他の用例はこちらの記事を参考にしてみてください。

https://qiita.com/puchi2121/items/c96219a731106c44316e


# 2. 比較演算子の連結

Pythonでは、比較演算子を連結できます。
```Python
a = 12.345
if 1 < a < 100:
    print(True)
# True
```
使う場面はないですが、文法上こんなこともできます。
```Python
1 < a > 10  # same as `1 < a and a > 10`
1 in [1, 2, 3] in [[1, 2, 3], [4, 5, 6]]
# True
# True
```
参考：

https://docs.python.org/ja/3/reference/expressions.html#comparisons


# 3. 短絡評価

Pythonでは、`and/or`による論理式の評価は、全体の真理値が決定された時点で終了します↓
> 式 x and y は、まず x を評価します; x が偽なら x の値を返します; それ以外の場合には、 y を評価した結果値を返します。
> 式 x or y は、まず x を評価します; x が真なら x の値を返します; それ以外の場合には、 y を評価した結果値を返します。
> *https://docs.python.org/ja/3/reference/expressions.html#boolean-operations* より

また、`and/or`が`True/False`を返すとは限らず、最後に評価された値が返されます。
したがって、以下のような結果となります。
```Python
"a" and 1  # same as `1 if bool("a") else "a"`
"a" or 1  # same as `"a" if bool("a") else 1`
"" or 1
# 1
# 'a'
# 1
```
こちらの実用的な使用場面としては、Noneチェックが挙げられます。
```Python
def f(l: list | None = None):
    l = l or []
    print(l)

# 以下と等価
def f(l: list | None = None):
    if not l:
        l = []
    print(l)
```
:::note warn
問題になることはほぼないと思いますが、引数に空リスト(`[]`)を渡した場合にも、`l`に新たに`[]`が代入されます。
:::

参考：

https://docs.python.org/ja/3/reference/expressions.html#boolean-operations

https://qiita.com/keisuke-nakata/items/e0598b2c13807f102469


# 4. 内包表記(comprehension)

リストなどのイテラブルオブジェクトの要素を反復して、新たなリスト等を作成します。
```Python
l = [1, 2, 3, 4, 5]

[x ** 2 for x in l]
# [1, 4, 9, 16, 25]
[x ** 2 for x in l if x % 2 == 0]  # 条件に当てはまる要素(=2の倍数)のみが選ばれる
# [4, 16]
```
作成されるオブジェクトは、具体的には、
- リスト内包表記 (`[ 内包表記 ]`)
- 辞書内包表記 (`{ key : value for 要素 in イテラブル [if 条件] }`)
- 集合内包表記 (`{ 内包表記 }`)
- ジェネレータ式 (`( 内包表記 )`)

の4パターンがあります。

参考：

https://docs.python.org/ja/3/reference/expressions.html#displays-for-lists-sets-and-dictionaries


# 5. セイウチ演算子(walrus operator, `:=`)
対応：Python3.8〜

"walrus"は日本語にすると「セイウチ」です。
> 大きな構文の一部として、変数に値を割り当てる新しい構文 := が追加されました。 この構文は セイウチの目と牙 に似ているため、「[セイウチ演算子](https://en.wikipedia.org/wiki/Walrus#/media/File:Pacific_Walrus_-_Bull_(8247646168).jpg)」の愛称で知られています。
> *https://docs.python.org/ja/3/whatsnew/3.8.html#assignment-expressions* より

変数に代入しつつ、その値を返すことのできる式です。
変数が`None`であるかチェックし、`None`でない場合にはその変数の値を利用したい場合に、少々簡潔に表記することができます。
```Python
import re

s = "Hello world!"
if m := re.search("world", s):
    print(m.group())
if (m := re.search("japan", s)) is not None:  # :=は結合性が低いので()で囲う必要がある
    print(m.group())
# world
```
リスト内包表記と組み合わせることで、関数(以下の例では`re.search`)を2回呼び出すのを防ぐこともできます。
```Python
l = ["a1", "b2", "c"]
[m.group() for x in l if (m := re.search(r"\d", x))]  # 文字列リストから数字を取り出す
# ['1', '2']
```

参考：

https://docs.python.org/ja/3/reference/expressions.html#assignment-expressions


# 6. for-else文

forループが`break`によって終了されなかった場合の処理を`else:`以下に定義することができます。
```Python
l = [2, 1, 3]
for i in l:
    print(i)
    if i >= 5:
        break
else:
    print("smaller than 5")
# 2
# 1
# 3
# smaller than 5
```
`l = [2, 5, 3]`の場合には、条件に引っかかり`break`されるため、出力が
```Python
# 2
# 5
```
となり、elseの中身は実行されません。

for-elseのメリットとしては、制御フロー変数の不要化が挙げられます。
これを使わないと以下のようになり、余計な変数を追う必要が出てきます。
```Python
f = True  # これが制御フロー変数
for i in l:
    print(i)
    if i >= 5:
        f = False
        break
if f:
    print("smaller than 5")
```


# 7. match文
対応：Python3.10〜

対象の値とパターンをマッチングし、処理を分岐させることができます。
```Python
l = [1, 2]
match len(l):
    case 0:
        print("empty")
    case 1 | 2:
        print("single or double")
    case _:
        print("more than 2")
# single or double
```
match文を使わないと以下のようになります。
```Python
if len(l) == 0:
    print("empty")
elif len(l) == 1 or len(l) == 2:
    print("single or double")
else:
    print("more than 2")
```
match文の方がスッキリした見た目になることがわかると思います。

また、他にも
```Python
match l:
    case []:
        print("empty")
    case [x]:
        print(f"first: {x}")
    case [x, y]:
        print(f"first: {x}, second: {y}")
    case _:
        print("many")
# first: 1, second: 2
match l:
    case list(x):
        print("list")
    case tuple(x):
        print("tuple")
    case _:
        print("other")
# list: [1, 2]
```
にような、構造やクラスによる複雑なマッチングもできます。

参考：

https://docs.python.org/ja/3/reference/compound_stmts.html#the-match-statement

https://qiita.com/ksato9700/items/3ce4c68c0d713874b693


# まとめ
他にも色々書きたいことはありますが、長くなりそうなので一旦ここまで。

Pythonにはまだまだ便利で面白いテクニックがたくさんあります。
また気が向いたら続編も書こうと思います。

最後に、この記事が面白いと思ってくださった方、またはもっと深いことを知りたいと思った方はぜひ以下の記事も読んでみてください！

https://qiita.com/CinnamonSea2073/items/cec093f5a9298aadcdc1