文系でも分かる!Pythonプログラミング - 内包表記 / "".join( ) / zip( ) / 0x~(hex( ))
← preview
next →
join
" " . join( )
>> join ( ジョイン )
= ( 複数のものを ) 接合する、結び合わせる。
他の意味は割愛。
[ 内包表記 ] を知った時、僕はこう思いました。
って。
具体的にはこうです。👇
# 繋げて出力したいのに...
name = ["つ","き","が","み"," ","ら","い","と"]
print([n for n in name], end="")
# >>> ['つ', 'き', 'が', 'み', ' ', 'ら', 'い', 'と']
# 改行して出力したいのに...
aiueo = ["あいうえお","かきくけこ","さしすせそ",
"たちつてと","なにぬねの","はひふへほ",
"まみむめも","やゐゆゑよ","らりるれろ",
"わ を ん"]
print([f"{a}\n" for a in aiueo])
# >>>['あいうえお\n', 'かきくけこ\n', 'さしすせそ\n',
# 'たちつてと\n', 'なにぬねの\n', 'はひふへほ\n',
# 'まみむめも\n', 'やゐゆゑよ\n', 'らりるれろ\n',
# 'わ を ん\n']
ほらぁ〜〜〜〜
やっぱfor文使うしかないじゃん!!
...と思う事、
あ〜りますよね〜〜ぇ??(通販)
そんな時に便利なのが、
この「 " " . join( ) 」メソッド!!
\ ワ〜〜〜〜オ!!/
こちらのサンプルコードをご覧下さい。
name = ["つ","き","が","み"," ","ら","い","と"]
join_name = "".join(name)
print(join_name)
# >>> つきがみ らいと
リストの要素が全てくっ付いて出力されました。
これが「 " " . join( ) 」の機能です。
「 " " . 」この部分が何の為に必要なのか
気になりますよね。
この記述で
値と値の "繋ぎ目の文字" を
指定するんです。
例えば、「 "/". join( ... ) 」と書くと...
name = ["つ","き","が","み"," ","ら","い","と"]
join_name = "/".join(name)
print(join_name)
# >>> つ/き/が/み/ /ら/い/と
値と値の間に「 / 」が付きました。
もう分かりましたよね。
「"".join( )」←こう書けば
値と値の間に何も挟まずに繋ぎ合わせる
って意味になるわけです。
値と値の間に何も挟まずに
繋ぎ合わせたい事の方が多いんだから
「"".」を省いて「 join( ) 」
って書けばじゃないかと思うかもしれません。
しかしそうはいかない。
「 join( ) 」という関数は定義されていないのです。
関数とメソッドの違いについては
改めて記事を書きますが、
簡単に言ってしまうと...
「 dict_name.keys( ) 」
「 dict_name.values( ) 」
「 dict_name.items( ) 」
「 list_name.append( ) 」
「 list_name.remove( ) 」
のように
「 . (ドット) 」を使う必要があるものを
「 メソッド 」と呼ぶのです。
それに対して「 関数 」は
「 print( ) 」や「 len( ) 」のように
それ単体で呼び出すことができる。
ですから、joinメソッドの場合
"繋ぎ目の文字". join( [iterable_object] )
という書き方をしないとエラーになるので
忘れないように注意しましょう。
" " . join( [ 内包表記 ] )
この 「 "".join( ) 」は
str型(文字列)どうしを繋ぐための
メソッドとなっています。
もし、[iterable_object] 内に
str型以外の要素が含まれていた場合、
TypeErrorになってしまいます。
「 "".join( ) 」は
str型(文字列)専用のメソッド。
ほんなら、
str型以外のオブジェクトが格納されている
[ iterable_object ] に対して使う場合...
先に型を変換してあげる必要がありますよね?
しかし...
data = [1,2,3,4,5]
join_data = "".join(str(data))
print(join_data)
# >>> [1, 2, 3, 4, 5]
👆これでは格納された値ではなくて
リスト自体の型を変換した事に
なってしまいます。
つまり、
"[1, 2, 3, 4, 5]"
☝️こうなってしまったってこと。
見た目がリストの
str型オブジェクトを作っただけってことです。
こういう変換の仕方では
「 " " . join( ) 」を使う意味がありません。
ここで内包表記を使うわけです。
data = [1,2,3,4,5]
join_data = "".join([str(d) for d in data])
print(join_data)
# >>> 12345
格納された要素を1つ1つ順番に取り出して
str( )で型を変換していきます。
すると、
[1, 2, 3, 4, 5] 👉 ['1', '2', '3', '4', '5']
このようになるので、
「 " " . join( [iterable_object] ) 」を
使えるようになるって寸法です。
format関数 / f-strings
を使ってstr型に変換してもいいですね。👇
join_data = "".join(["{}".format(d) for d in data])
join_data = "".join([f"{d}" for d in data])
内包表記で生成したリストを
改行して出力するには、
#aiueo = ["あいうえお","かきくけこ","さしすせそ","たちつてと",(以下略)]
print("".join([f"{a}\n" for a in aiueo]))
# >>> あいうえお
# かきくけこ
# さしすせそ
# たちつてと
# なにぬねの
# はひふへほ
# まみむめも
# やゐゆゑよ
# らりるれろ
# わ を ん
こう書けばいいです。
エスケープシーケンスの
"\n" または "¥n" を使うのです。
細かい事ですけれど...
この書き方をした場合
print( )は1度しか呼び出されません。
print( )がコンソール出力した時に
「 >>> 」を使うようにしているので
# >>> あいうえお ← print("あいうえお")
# >>> かきくけこ ← print("かきくけこ")
# >>> さしすせそ ← print("さしすせそ")
👆こうではなくて
# >>> あいうえお ← print("あいうえお\n"
# かきくけこ "かきくけこ\n"
# さしすせそ "さしすせそ\n")
👆こう書かれている事に注意して下さい。
zip
ネストとアンパック代入
例えば、
👆こんなテキストを出力しようと思って
3つのリスト用意したとしましょう。👇
list_x = [1,2,3,4]
list_y = ["墾田永年私財法",
"大化の改新",
"中臣鎌足",
"飛鳥文化アタック"]
list_z = ["こんでんえいねんしざいほう",
"たいかのかいしん",
"なかとみのかまたり",
"あすかぶんかあたっく"]
( 4, "飛鳥文化アタック", "あすかぶんかあたっく" ) のように
3つのリストから
一挙にドーンと値を取り出して
アンパック代入できたら楽なのですが...
エラーになってしまいました。
当然と言えば当然ですよね。
for x, y, z in (list_x, list_y, list_z) :
👆こう書いてしまったら、
x = list_x
y = list_y
z = list_z
こうなるんですから。
アンパック代入できるのってさ、
for a,b in [ 1, 2 ]:
👆 変数の数 と 要素の数 が同じか
for k,v in { k1:v1, k2:v2, k3:v3 }.items( ):
👆 変数の数 と 一度に取り出せる要素の数 が同じか
っていうこのどっちかなわけですよ。
dict = {"key1":"value1",
"key2":"value2",
"key3":"value3"}
print(dict.items())
# >>> dict_items([('key1', 'value1'),
# ('key2', 'value2'),
# ('key3', 'value3')])
辞書名.items( ) を使うと
タプルがネストされたリストが返ってきます。
タプルを1つ取り出すと
("key1", "value1") ← こうなっている。
だからこそ
k,v = ("key1", "value1")
このように2つの変数でアンパック代入できるのです。
3つのリストから値を一気に取り出して
3つの変数にアンパック代入するためには、
[( list_x[0], list_y[0], list_z[0] ),
( list_x[1], list_y[1], list_z[1] ),
( list_x[2], list_y[2], list_z[2] ),
( list_x[3], list_y[3], list_z[3] )]
こういう、
タプルがネストされた2次元リストを
作成しなければなりません。
具体的に書くと...👇
[(1, '墾田永年私財法', 'こんでんえいねんしざいほう'),
(2, '大化の改新', 'たいかのかいしん'),
(3, '中臣鎌足', 'なかとみのかまたり'),
(4, '飛鳥文化アタック', 'あすかぶんかあたっく')]
こうですね。
ちゃんと書こうと思ったら
#list_x = (省略)
#list_y = (省略)
#list_z = (省略)
for i in range(len(list_x)):
list_xyz = [(list_x[i], list_y[i], list_z[i])]
for x,y,z in list_xyz:
print(f"Q.{x} -> {y}({z})")
# >>> Q.1 -> 墾田永年私財法(こんでんえいねんしざいほう)
# >>> Q.2 -> 大化の改新(たいかのかいしん)
# >>> Q.3 -> 中臣鎌足(なかとみのかまたり)
# >>> Q.4 -> 飛鳥文化アタック(あすかぶんかあたっく)
こうする他ありません。for文の多重ループです。
しかし、この方法は非常に面倒です。
こういう手間を思いっきり省いてくれるのが
今回紹介する zip関数 です。
for x,y,z in zip( list1, list2, list3 ):
>> zip ( ジップ )
= ジッパーで締める。口にチャックする。
〔コンピュータ〕圧縮すること。圧縮したファイルの形式。
zip関数 の 引数 として
[ iterable_object ] を渡す必要があるので
>> UPPER(アッパー) = 大文字の意
>> lower(ロワー/ロウアー) = 小文字の意
という2つの [リスト] を用意しました。
UPPER = ["A","B","C","D"]
lower = ["a","b","c","d"]
zip_obj = zip(UPPER, lower)
print(zip_obj)
# >>> <zip object at 0x122ccc388>
しかし、出力結果はリストやタプル
などではありません。
zip型オブジェクト
というものが出来上がったようです。
zip型オブジェクト は
list型オブジェクトではないわけですから、
具体的にどんな中身になっているのかは
list関数などを使ってやらん事には分かりません。
lower = ["a","b","c","d"]
UPPER = ["A","B","C","D"]
zip_obj = zip(lower, UPPER)
print(list(zip_obj)) # list関数で型を変換
# >>> [('a', 'A'),
# ('b', 'B'),
# ('c', 'C'),
# ('d', 'D')]
タプルがネストされたリストができましたね。
このリストから
ネストされたタプルを1つ1つ取り出せれば、
アンパック代入する事ができるわけだ。
というわけで
zip関数の引数にした [iterable_object] の数と
同じ数の変数を用意してアンパック代入してやります。
① for文の場合
#list_x = (省略)
#list_y = (省略)
#list_z = (省略)
for x,y,z in zip(list_x, list_y, list_z):
print(f"Q.{x} -> {y}({z})")
# >>> Q.1 -> 墾田永年私財法(こんでんえいねんしざいほう)
# >>> Q.2 -> 大化の改新(たいかのかいしん)
# >>> Q.3 -> 中臣鎌足(なかとみのかまたり)
# >>> Q.4 -> 飛鳥文化アタック(あすかぶんかあたっく)
②"".join( [内包表記] )の場合
#list_x = (省略)
#list_y = (省略)
#list_z = (省略)
list_xyz = "".join([f"Q.{x} -> {y}({z})\n"
for x,y,z in zip(list_x, list_y, list_z)])
print(list_xyz)
# >>> Q.1 -> 墾田永年私財法(こんでんえいねんしざいほう)
# Q.2 -> 大化の改新(たいかのかいしん)
# Q.3 -> 中臣鎌足(なかとみのかまたり)
# Q.4 -> 飛鳥文化アタック(あすかぶんかあたっく)
成功!!!
簡単だね!!!
....ん?
おかしいと思いませんか?
zip関数が返してくるのは
リストやタプルなんかじゃないから
list関数でわざわざ型の変換をしたのに
上のfor文では
別に型の変換はしていませんよね?
# こうじゃなくて
for x,y,z in list(zip(list_x, list_y, list_z)):
# こうしている
for x,y,z in zip(list_x, list_y, list_z):
気付きました???
これ結構大事なことなんですよ。
2つのリストを
zip関数の引数にしてやると...
UPPER = ["A","B","C","D"]
lower = ["a","b","c","d"]
zip_lists = zip(UPPER, lower)
print(zip_lists)
# >>> <zip object at 0x122ccc388>
< zip object at 0x〜 >
という出力結果になりました。
一度スルーしたこれは一体何なのか??
って話ですよ。
詳しく見ていきたいと思うんですが
長くなるので今回はここまで。
次の記事へ。