pythonのリスト

このページは

javascriptの配列とリストと比較するためのPython版です。

Pythonの学習中の記録ですので、全体の展望ができていません。簡便な比較リファレンスを目指します。

リストの生成

pythonでは配列という言葉は出てこず、リストで統一されているようです。振る舞いとしてはjavascriptと同程度に配列でありリストでもあるのですが、歴史的な理由でしょう。内部構造としてはリストがしっくりするようです。

要素の値をコンマ区切りで書いたものからリストを生成できます。各要素へのアクセスは配列のように添え字を使うことができます。

names = ["mike","tama","kuro"]
print(names[2])
print(names[0])
print(names)
print(len(names))
names[1]="akame"
print(names)

実行結果です。

kuro
mike
['mike', 'tama', 'kuro']
3
['mike', 'akame', 'kuro']

各要素への参照は角括弧に番号を入れたもの([0]のような)を使って行います。

要素の数は、len() という関数で得られます。

タプルもある

pythonにはリストの他にタプルというものがあります。データの更新ができないリストです。ほぼ同様に使うことができます。定数のようにして、よく使われます。リストは[ ]、タプルは( ) でくくります。

names = ("mike","tama","kuro")
print(names[2])
print(names[0])
print(names)
print(len(names))
kuro
mike
('mike', 'tama', 'kuro')
3

要素の種類は混在可能

javascriptと同様に要素の種類が混在でも構いません。

names = ["mike","tama","kuro"]
ntuple = ("pochi","shiro","koro","masaru")
iroiros = ["mike",365,1.2,True,names,ntuple]
print(iroiros[0])
print(iroiros[1])
print(iroiros[2])
print(iroiros[3])
print(iroiros[4])
print(iroiros[5])
print(iroiros)
print(type(iroiros[0]))
print(type(iroiros[1]))
print(type(iroiros[2]))
print(type(iroiros[3]))
print(type(iroiros[4]))
print(type(iroiros[5]))
print(type(iroiros))

実行結果です。

mike
365
1.2
True
['mike', 'tama', 'kuro']
('pochi', 'shiro', 'koro', 'masaru')
['mike', 365, 1.2, True, ['mike', 'tama', 'kuro'], ('pochi', 'shiro', 'koro', 'masaru')]
<class 'str'>
<class 'int'>
<class 'float'>
<class 'bool'>
<class 'list'>
<class 'tuple'>
<class 'list'>

"mike"はstr、これは文字列。365はint、これは整数。type関数で確認することができます。

空の配列をつくる

生成の時に要素が空であれば、要素数0の配列ができます。

karas = [];

appendメソッドで要素を追加することで要素数が増えます。存在しない要素に値を代入したり参照したりはできません。期待通りの振る舞いです。タプルは変更できませんから、要素数追加もできません。

要素の種類が混在の時とほとんど同じことをやってます。そこで、表示にはforを使ってみます。

iroiros = []
iroiros.append("moji")
iroiros.append(3128)
iroiros.append(2.7182)
iroiros.append(1==1)
iroiros.append(['mike','tama'])
iroiros.append((1,2))
for item in iroiros:
    print(item,type(item))
print('-----')
print(iroiros,type(iroiros))

実行結果です

moji <class 'str'>
3128 <class 'int'>
2.7182 <class 'float'>
True <class 'bool'>
['mike', 'tama'] <class 'list'>
(1, 2) <class 'tuple'>
-----
['moji', 3128, 2.7182, True, ['mike', 'tama'], (1, 2)] <class 'list'>

要素数と初期値を指定する配列

そもそも値を入れる場所をあらかじめ用意する配列という概念がないので、要素数を指定しません。しかし、初期値を用意することはできます。256の要素が全部0であるようなリストです。

2つやり方があります。

iroiros = [0]*256
iroiros = [0 for i in range(256)]

後者は内包表記と呼ばれるものです。

iroiros = [0]*256
#iroiros = [0 for i in range(256)]
iroiros[255] = 3
iroiros[254] = "abc"
iroiros[253] = 2.7182
iroiros[0] += 1
iroiros[1] = iroiros[2] = 8
print(len(iroiros))
print(iroiros[0])
print(iroiros[1])
print(iroiros[2])
print(iroiros[3])
print(iroiros[253])
print(iroiros[254])
print(iroiros[255])

実行結果は、

256
1
8
8
0
2.7182
abc
3

a=b=3 は、a=3とb=3を同時に実行するものです。Javaでも使えます。

繰り返し機構

for文は多くの言語で使える王道です。3つ紹介します

for item in iroiros:
for i in range(len(iroiros)):
for i, item in enumerate(iroiros):

最初のものはforeachそのものです。indexが不要であれば、これが最適でしょう。

2つめはiが、0,1,2,...と増えていくのでindexとして使います。

enumerate()は、(index,item)のタプルを返すので、それをiとitemに代入するものです。

names = ["mike","tama","kuro"]
for name in names:
   print(name)
for i in range(len(names)):
   print(i,names[i])
for i, name in enumerate(names):
   print(i,name)

実行結果です

mike
tama
kuro
0 mike
1 tama
2 kuro
0 mike
1 tama
2 kuro

リストらしい活用

もともとリストですが、上記ではJavascriptに合わせてやや配列的な使い方でした。リストラしい活用に触れます。

appwndは最後に要素を追加します。戻値はありません。

popは最後の要素を削除し、削除した要素の値を返します。

saba,hokke,iwashi,shishamo をappendでリストに取り込んでpopで取り出して書き出します。

仕組みを理解するために、一回のappendごとにリストを書いていき、4つ読んだら一回のpopのごとに戻値とリストを書いています。

fishes=('saba','hokke','iwashi','shishamo')
fishlist = []
for fish in fishes:
    fishlist.append(fish)
    print(fishlist)
while len(fishlist)>0:
    fish = fishlist.pop()
    print(fish,fishlist)

実行結果です

['saba']
['saba', 'hokke']
['saba', 'hokke', 'iwashi']
['saba', 'hokke', 'iwashi', 'shishamo']
shishamo ['saba', 'hokke', 'iwashi']
iwashi ['saba', 'hokke']
hokke ['saba']
saba []

Listの主要なメソッド

戻値メソッド説明
Noneappend(x) リストの末尾に要素を一つ追加する
Noneextend(iterable) イテラブルのすべての要素を対象のリストに追加し、リストを拡張する。
Noneinsert(i, x) iの位置に要素を挿入する。i=len(list)なら末尾
Noneremove(x) リスト中で x と等しい値を持つ最初の要素を削除します。該当する要素がなければ ValueError 。
xpop() リストの末尾の要素を削除して、その要素を返す。
xpop(i) iの位置にある要素をリストから削除して、その要素を返す。
Noneclear() リスト中の全ての要素を削除する。
iindex(x) x と等しい値を持つ最初の要素の位置を返す。 該当する要素がなければ ValueError 。
iindex(x,start[,end]) x と等しい値を持つ要素をstart位置から探して添字を返します。 該当がなければ ValueError 。 end があればその直前までが探索範囲。返される添字は、リストの先頭からの位置。
ncount(x) x の出現回数を返す。
Nonesort(key=None, reverse=False) インプレース (元のデータを演算結果で置き換) でソートする。
Nonereverse() インプレースで逆順にする。
listcopy() リストの浅い (shallow) コピーを返します。a[:] と等価です。
★値の参照(戻値はすべて x)
↑x [i]
x [0]← List →x [-1]
↑x [i] = x
★要素数の増減をともなうメソッド(戻値はNがNone(なし), xは値)
⇩N .insert(i, x)
N .insert(0, x)⇨ List ⇦N .append(x)
⇦N .extend((x,y,..,z))
x .pop(0)⇦ ⇨x .pop()
⇩x .pop(i)
⇩N .remove(x)

メソッド使用例と戻値確認

戻値は目的上必要なもの以外はNone(なし)が原則。

fishlist = ['saba','hokke','iwashi','shishamo']
print('ini',fishlist)
ap = fishlist.append('karei')
print('app',ap,fishlist)
ex = fishlist.extend(('tara','nishin'))
print('ext',ex,fishlist)
rm = fishlist.remove('hokke')
print('rmv',rm,fishlist)
rm = fishlist.pop(1)
print('po1',rm,fishlist)
rm = fishlist.pop()
print('pop',rm,fishlist)
rm = fishlist.clear()
print('clr',rm,fishlist)

実行結果です

ini ['saba', 'hokke', 'iwashi', 'shishamo']
app None ['saba', 'hokke', 'iwashi', 'shishamo', 'karei']
ext None ['saba', 'hokke', 'iwashi', 'shishamo', 'karei', 'tara', 'nishin']
rmv None ['saba', 'iwashi', 'shishamo', 'karei', 'tara', 'nishin']
po1 iwashi ['saba', 'shishamo', 'karei', 'tara', 'nishin']
pop nishin ['saba', 'shishamo', 'karei', 'tara']
clr None []

さらに

fishlist = ['saba','hokke','iwashi','shishamo']
print('ini',fishlist)
ins = fishlist.insert(3,'hokke')
print('ins',ins,fishlist)
idx = fishlist.count('hokke')
print('cnt',idx,fishlist)
idx = fishlist.index('hokke')
print('idx',idx,fishlist)
idx = fishlist.index('hokke',idx+1)
print('idx',idx,fishlist)
sor = fishlist.sort()
print('sor',sor,fishlist)
set = fishlist[3] = 'replace'
print('set',set,fishlist)
rm = fishlist.pop(0)
print('po0',rm,fishlist)
rev = fishlist.reverse()
print('rev',rev,fishlist)

実行結果です

ini ['saba', 'hokke', 'iwashi', 'shishamo']
ins None ['saba', 'hokke', 'iwashi', 'hokke', 'shishamo']
cnt 2 ['saba', 'hokke', 'iwashi', 'hokke', 'shishamo']
idx 1 ['saba', 'hokke', 'iwashi', 'hokke', 'shishamo']
idx 3 ['saba', 'hokke', 'iwashi', 'hokke', 'shishamo']
sor None ['hokke', 'hokke', 'iwashi', 'saba', 'shishamo']
set replace ['hokke', 'hokke', 'iwashi', 'replace', 'shishamo']
po0 hokke ['hokke', 'iwashi', 'replace', 'shishamo']
rev None ['shishamo', 'replace', 'iwashi', 'hokke']

配列中の値を探して削除

removeを使って要素を削除する場合、存在しなければエラーで停止します。その対策です。

indexOfの様に、index(値)で探すのも、見つからない場合はエラーですからだめです。

対策1: count(値)で探してremove(値)で削除

対策2: in関数を使う方法

対策3: try: except でも可能ですが、ここでは扱いません。

対策1

fishlist = ['saba','hokke','iwashi','shishamo']
print('ini',fishlist)
rmv = 'ika'
if fishlist.count(rmv)>0:
    fishlist.remove(rmv)
    print(rmv+' removed.')
else:
    print(rmv+' not here.')
rmv = 'iwashi'
if fishlist.count(rmv)>0:
    fishlist.remove(rmv)
    print(rmv+' removed.')
else:
    print(rmv+' not here.')
print('now',fishlist)

対策2

fishlist = ['saba','hokke','iwashi','shishamo']
print('ini',fishlist)
rmv = 'ika'
if rmv in fishlist:
    fishlist.remove(rmv)
    print(rmv+' removed.')
else:
    print(rmv+' not here.')
rmv = 'iwashi'
if rmv in fishlist:
    fishlist.remove(rmv)
    print(rmv+' removed.')
else:
    print(rmv+' not here.')
print('now',fishlist)

実行結果はどちらも同じです

ini ['saba', 'hokke', 'iwashi', 'shishamo']
ika not here.
iwashi removed.
now ['saba', 'hokke', 'shishamo']

もちろん else や print は不要であれば省きます。

三項演算子の様なもの

Javaacriptで必要があって、三項演算子(条件?trueの時の式:falseの時の式)を使いました。Javaではそれに合わせて使いました。pythonで似たような効果のある書き方はこうなります。

(変数) = (条件がTrueのときの値) if (条件) else (条件がFalseのときの値)

三項演算子は単項演算子、二項演算子の流れから来る名称ですが、名前を聞いた反応が「3項?そんなことができるのか?...あ、そうね...」で、式を見た反応が「何を言ってるんだ」で、奇異さ加減がちょうどよくマッチする名前です。条件演算子と呼ぶ言語もあるようですが、これではしっくり来ません。でも、pythonでは演算子には見えません。ドキュメントでは条件式 (Conditional Expressions)の項に書いてあります。

他の三項演算子を知っていると順番が逆と思いますが、こちらを先に見ていたらすんなり受け入れられると思います。英語そのままの表現です。

使ってみます。

fishlist = ['saba','hokke','iwashi','shishamo']
print('ini',fishlist)
rmv = 'ika'
retv = fishlist.remove(rmv) if rmv in fishlist  else 'not found'
print('after',retv,fishlist)
rmv = 'iwashi'
retv = fishlist.remove(rmv) if fishlist.count(rmv)>0  else 'not found'
print('after',retv,fishlist)

実行結果です

ini ['saba', 'hokke', 'iwashi', 'shishamo']
after not found ['saba', 'hokke', 'iwashi', 'shishamo']
after None ['saba', 'hokke', 'shishamo']

やりたいことを先に書けるので、しっくりきます。else以下は必要です。

削除の時は戻値はNoneなので、書かなくても良いという場合は、

fishlist.remove(rmv) if rmv in fishlist  else  print(rmv,' not found')
fishlist.remove(rmv) if fishlist.count(rmv)>0  else  print(rmv,' not found')

も可能です。

これもいらないという場合、elseは必要なので、

fishlist.remove(rmv) if rmv in fishlist  else None

です。

nopにあたるpassが使えるかと思ったのですが、だめでした。これが気に入らなければ、素直に

if rmv in fishlist: fishlist.remove(rmv)

とすればいいだけです。

split

split("区切り文字")は文字列を区切り文字で区切って、分けたものを要素にした配列を生成して返します。pythonでは、リストの初期化が楽なので出番がなかったので、ここにおいておきます。

Javaでもできる方法は、

fstr = 'saba,hokke,iwashi,shishamo'
fishlist = fstr.split(',')
#['saba', 'hokke', 'iwashi', 'shishamo']

さらに半角スペースで区切られているときには( )に区切り文字を指定しなければ、複数のスペースがあっても一つの区切りとしてくれます。

fstr = 'saba hokke iwashi  shishamo'
fishlist = fstr.split()
#['saba', 'hokke', 'iwashi', 'shishamo']

リストのリスト

すでに、「要素の種類は混在可能」でやっています。Javascriptと同じプログラムを作れます。

basename = ["アイス","ヨーグルト"];
sauce = ["ブルーベリー","黒蜜","練乳","チョコ"];
topping = ["イチゴ","バナナ","小倉餡"];
dessertmenu = [basemenu,sauce,topping];

basename,sauce,toppingという分類名はリストでは失われて番号になりますが、リストのリストを必要としたのは数学関係のプログラムでしたので、0,1,2という連番で構いませんでした。必要ならリストの代わりに辞書を使います。

example1 = dessertmenu[2][0]+dessertmenu[1][2]+dessertmenu[0][0];
# イチゴ練乳アイス

basenameに"かき氷"を加えたければ、

dessertmenu[0].append("かき氷");

drinkメニューを加えたければ、

dessertmenu.append(["コーヒー","紅茶","ソーダ"]);

で可能です。

basename = ["アイス","ヨーグルト"];
sauce = ["ブルーベリー","黒蜜","練乳","チョコ"];
topping = ["イチゴ","バナナ","小倉餡"];
dessertmenu = [basename,sauce,topping];
example1 = dessertmenu[2][0]+dessertmenu[1][2]+dessertmenu[0][0]
print('参照例',example1)
print('追加前',dessertmenu[0])
dessertmenu[0].append("かき氷");
print('追加後',dessertmenu[0])
print('飲物追加前',dessertmenu)
dessertmenu.append(["コーヒー","紅茶","ソーダ"]);
print('飲物追加後',dessertmenu)
basename.append("パスタ");
print('!!',dessertmenu)

やってみます。

参照例 イチゴ練乳アイス
追加前 ['アイス', 'ヨーグルト']
追加後 ['アイス', 'ヨーグルト', 'かき氷']
飲物追加前 [['アイス', 'ヨーグルト', 'かき氷'], ['ブルーベリー', '黒蜜', '練乳', 'チョコ'], ['イチゴ', 'バナナ', '小倉餡']]
飲物追加後 [['アイス', 'ヨーグルト', 'かき氷'], ['ブルーベリー', '黒蜜', '練乳', 'チョコ'], ['イチゴ', 'バナナ', '小倉餡'], ['コーヒー', '紅茶', 'ソーダ']]
!! [['アイス', 'ヨーグルト', 'かき氷', 'パスタ'], ['ブルーベリー', '黒蜜', '練乳', 'チョコ'], ['イチゴ', 'バナナ', '小倉餡'], ['コーヒー', '紅茶', 'ソーダ']]

最後の例(!!)で、配列に入るのは参照であることがわかります。