Python3一行書きの手法まとめ


なにこれ

自分が Python のワンライン書きにハマって数年が経ったのでこれを機に使ってた手法を軽く纏めてみました。

代入1

Before
line = input()
print(line)
After
print(input())

読めばわかるかもしれないですが、変数に代入する必要がなかったらそのまま突っ込んじゃえばいいって意味ですね。

代入2

Before
x = int(input())
print(f'x={x},Y={2*x+1}')
After
(lambda x:print(f'x={x},Y={2*x+1}'))(int(input()))

変数が必要なら lambda で突っ込んじゃえって意味ですね。
lambda は関数なので、左側に関数、右側に引数という形にするとちゃんと動きます。
要は関数作ってそのまま使ってる感じです。

別の手法

another
print(f"x={locals().setdefault('x',int(input()))},Y={2*x+1}")

名前空間に直接ぶち込んじゃえって意味ですね。
python は名前空間を辞書型1で管理しており、名前空間のグローバルスコープの内容はglobals()、ローカルスコープはlocals()で取得できます。
なので、それで呼び出した dict に直接追加しています。
setdefault()は戻り値があるので使っています。

一時期使っていましたが、lambda の方を知ってからはそっちを使ってますね。これ長いので。

条件分岐(三項演算子的な)

Before
if age >= 18:
    print("成年")
else:
    print("未成年")
After
print(["未成年","成年"][age>=18])

Python の暗黙の型変換を利用した if 文です。if 文は使ってません。
これは、True,Falseがそれぞれ1,0になるのを利用しました。

> int(True)
1
> int(False)
0

体感ですが三項演算子より読みやすいですね。

応用(文字列のスライス)

print("未成成年年"[age>17::2])

「読みやすいですね」

import

Before
import math
print(math.sqrt(4))
# => 2.0
After
print(__import__("math").sqrt(4))
# => 2.0

python の組み込み関数に__import__()というものがあります。
import が必要な関数やメソッドを速攻で使えます。それだけです。

ちなみに強く推奨されていないので注意が必要です。2

型変換

map

Before
line = input()                 # 入力
array = line.split()           # 分割
for i in range(len(array)):
    array[i] = int(array[i])   # 型変換
After
array = list(map(int, input().split()))

map()は第2引数のイテレータになれるオブジェクトに入っているすべての値に第1引数の呼び出し可能なオブジェクトを適応させることができる関数です。
イテレータになれるオブジェクトは list や dict 等、呼び出し可能なオブジェクトは関数やメソッド等のことです。
戻り値は map オブジェクトなので list に型変換する必要があります。

range

連続した数値はrange()が作り出してくれるので、それを list に変換すれば一瞬で済みます。

Before
array = []
for i in range(5):
    array.append(i)
# array = [0, 1, 2, 3, 4]
After
array = list(range(5))
# array = [0, 1, 2, 3, 4]

strの乗算

Before
print("Hello", end="")
if flag:
    print(" World", end="")
print("!!")
After
print("Hello" + " World"*flag + "!!")

str と int を乗算すると int の分だけ文字列が増えます。
int が 0 の場合、文字列が消えます。

> 'a'*4
'aaaa'
> 'hoge'*2
'hogehoge'
> 'ten-gallon hat'*False
''

悪いこと

型変換を悪用すると fizzbuzz を if, for 文なしで書けます。

fizzbuzz.py
print(*map(lambda x:x%3//2*'Fizz'+x%5//4*'Buzz'or f'{x+1}',range(int(input()))),sep='\n')

可読性は皆無ですね。

あとがき

コードゴルフには使用できないようなものもたくさんありますね。
ぶっちゃけて言うと可読性が悪くなるのでワンライナーはお勧めしません。
逆に可読性悪いのが書きたくなった場合はワンライナーをお勧めします。

他にもありましたら是非コメントにお願いします。
それと読みにくい場所がありましたら遠慮なく言ってください。訂正します。

参考文献


  1. 将来変わるかもしれないです。 

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