📚

CodinGame Clash of Code で知ったpythonのかっこいい書き方メモ

2022/03/21に公開
2

python初心者が適宜追記していきます

リストrからi番目の要素を削除した新しいリストの作り方

o = r[:i] + r[i+1:]

独り言:コピーして削除するなら copy.copy(r).pop(i) でもできるが...
iとi+1を削除するとか、応用が効くのでなるほど。

文字列のリストlから先頭の文字だけを抜き出した新しいリスト

o = [v[0] for v in l]

独り言:リスト内包表記。これはひたすら慣れるしかない。

文字列中の1文字ずつを他のコレクションに

str = "abcde"
list(str)
set(str)

独り言:へー。

range関数

range([始まりの数値,] 最後の数値[, 増加する量])

range(10)     # 0,1,2,3,4,5,6,7,8,9
range(1,10)   # 1,2,3,4,5,6,7,8,9
range(1,10,2) # 1,3,5,7,9

独り言:へー。

リスト中の文字を結合

'-'.join(リスト)
# リスト中の文字列を'-'区切りで結合する。要素が文字列でない場合はエラーなので注意。

独り言:リスト内包表記と組み合わせて表現力が高そうです。

除算あれこれ

5/2   = 2.5 #int同士でも切り捨てずfloat型
10/2  = 5.0 #割り切れる場合でもfloat型
5//2  = 2   #切り捨ててint型
10//5 = 2   #もちろんint型
10.0//4 = 2   #float型!
10//4.0 = 2   #float型!
10//0.001 = 9999.0 #演算で誤差が出てる。

独り言: 切り捨てる除算は最低でも右辺値をintにしたほうが混乱少なそう

exit()

exit() #プログラムを終了する

独り言: main関数におけるreturn的に使えるし、何かの緊急回避でも使えるだろう。

組み込み関数にコレクションでなくジェネレータを渡す

sum(i for i in ranger(10))

この場合は無事に0~10の和を計算してくれる。少しだけタイプ量が減らせる。
独り言: 関数に放り込むだけならこのほうが適切なパターンは結構ありそう

リスト内包表記で辞書も初期化できる

{chr(k): k for k in range(128)}

独り言: python強い

まとめて代入

a,b=(b,a) if True else (2,3)

独り言: 右辺をタプル、またはリストの形式にしたら展開される。構造化束縛みたいだね。

カンマ区切りのprint出力

print(0,1,2,3) # 0 1 2 3

独り言: スペース区切りになるらしい。shortest勝負のときに使えそう。

文字列にindexアクセスで直接書き換えることはできない

s = "abc"
s[0] = "d"

これはだめ。
やるなら

s = "abc"
t = list(s)
t[0] = "d"
s = "".join(t)

こうなる。
または、(iの位置の文字を書き換えるとして)この記事の最初の方法を使って

s = "abc"
s = s[:i] + "d" + s[i+1:]

独り言: strがそもそも不変なので、新しい文字列を作らないといけないらしい。毎回新しい文字列を作るなんて処理コストが恐ろしい...という古い考えをアップデートするのじゃ。

strのsplit関数のデフォルトはスペース区切り

s = "a a a"
s.split()

独り言: 理解した

listのreversedはもとのリストを書き換え、かつ返り値はNone

l = [1,2,3]
l.reversed()

独り言: pythonのどれがもとの値を書き換えて、どれが書き換えないのかいつもわからなくなるよ

スライスを使って逆順にする

l = [1,2,3]
l = [::-1]

start,stopを省略=全体の選択。-1で逆順、ということらしい。
独り言: そういうイディオムだと思って覚える

リストにアスタリスクをつけるとアンパック

l = [1,2,3]
print(*l)

これで print(l[0],l[1],l[2]) の意味。 1 2 3 と出力。
独り言: 辞書だとどうなるのか確認してみよう

辞書のアンパックあれこれ

d = {"a":1, "b":2, "c":3}

print(d.keys())  # dict_keys(['a', 'b', 'c'])
print(*d.keys()) # a b c

print(d.values())  # dict_values([1, 2, 3]) 
print(*d.values()) # 1 2 3

print(d.items())  # dict_items([('a', 1), ('b', 2), ('c', 3)])
print(*d.items()) # ('a', 1) ('b', 2) ('c', 3)

print(d)  # {'a': 1, 'b': 2, 'c': 3}
print(*d) # a b c

独り言: 辞書そのものをアンパックするとkeys()のアンパックと同じ結果に。

文字列を指定回数繰り返した文字列

print("ab"*3) # ababab

独り言: 使い時は限られそうだが、知っていると威力抜群

二重ループのリスト内包表記

print([x*y for x in range(1,10)for y in range(1,10)]) # 1,2,3 ...(省略) ... 72 ,81

独り言: shortest向け

文字列の中に特定の文字列が含まれるかどうか

print('a' in 'abc')  # True
print('ab' in 'abc') # True
print('bc' in 'abc') # True
print('ac' in 'abc') # False

独り言: かんたん!

関数を代入

I=input
I() # input()が実行される

独り言: shortest向け

文字列中の文字を1文字ずつ列挙

for x in "abcde":
  print(str(x))

独り言: 文字列はイテレータ

何もしないif文内ではpass

if x==y:
  pass

独り言:そういえばそんなのもあったな

改行しないprintはend指定で空文字

print("xxx", end="")

独り言:つまり、末尾に任意の文字を指定することができる。デフォルトが改行コード、ということ。

subで正規表現置換

import re
s = "01abc"
s = re.sub("[012]", "", s)
print(s) # -> abc

独り言:reをimportする必要がある分のオーバーヘッドが惜しい

Discussion

pop_leftpop_left

リスト内包表記はリストのカッコを省略しても書ける

これは誤りで、 sum(i for i in n) でsumに渡されるのはジェネレーター式です。

https://docs.python.org/ja/3.7/reference/expressions.html#generator-expressions

>>> def f(argument):
...     print(type(argument))
...
>>> f([1 for _ in range(10)])
<class 'list'>
>>> f(1 for _ in range(10))
<class 'generator'>

ジェネレーター式と認識していない場合に埋め込みやすいバグの例として以下です。注意です。

>>> def g(argument):
...     for i in argument:
...             print(i)
...     for i in argument:
...             print(i)
...
>>> g([i for i in range(2)])
0
1
0
1
>>> g(i for i in range(2))
0
1
TaiyoTaiyo

コメントありがとうございます!
わかっていませんでした。記事を修正しました!