Python/リスト
Pythonにおけるリスト(List)は、複数の要素を格納できるデータ構造で、順序があります。以下は、Pythonのリストを操作する基本的な操作です。
- コード例
# リストの作成 my_list = [1, 2, 3, 4, 5] # 要素のアクセス print(my_list[0]) # 1を出力 print(my_list[-1]) # 最後の要素を出力 # スライス subset = my_list[1:4] # インデックス1から3(4未満)までの要素を取得 # 要素の追加 my_list.append(6) # リストの末尾に要素を追加 # 要素の挿入 my_list.insert(2, 7) # インデックス2の位置に要素7を挿入 # 要素の削除 my_list.remove(3) # 値が3の要素を削除 # インデックスを指定して削除 del my_list[2] # インデックス2の要素を削除 # リストの結合 new_list = my_list + [8, 9, 10] # リストの長さ length = len(my_list) # リストのループ for element in my_list: print(element) # リスト内包表記 squared_numbers = [x**2 for x in my_list]
これらはリストを使った基本的な操作です。リストは非常に柔軟で強力なデータ構造であり、さまざまな操作や機能が利用可能です。
Pythonのリストには、さまざまな演算子があります。以下に、リストでよく使用される主な演算子をいくつか示します。
- コード例
# 結合演算子 (+): 2つのリストを結合して新しいリストを作成します。 list1 = [1, 2, 3] list2 = [4, 5, 6] result = list1 + list2 # resultは[1, 2, 3, 4, 5, 6] # 繰り返し演算子 (*): リストを指定した回数繰り返します。 list1 = [1, 2, 3] result = list1 * 3 # resultは[1, 2, 3, 1, 2, 3, 1, 2, 3] # 比較演算子: リスト同士を比較するために、等号 (==) や不等号 (!=) を使用できます。 list1 = [1, 2, 3] list2 = [1, 2, 3] list3 = [4, 5, 6] print(list1 == list2) # True print(list1 != list3) # True # メンバーシップ演算子 (in, not in): 特定の要素がリストに含まれているかどうかを確認します。 list1 = [1, 2, 3] print(2 in list1) # True print(4 not in list1) # True
- 結合演算子 (
+
): 2つのリストを結合して新しいリストを作成します。 - 繰り返し演算子 (
*
): リストを指定した回数繰り返します。 - 比較演算子: リスト同士を比較するために、等号 (
==
) や不等号 (!=
) を使用できます。 - メンバーシップ演算子 (
in
,not in
): 特定の要素がリストに含まれているかどうかを確認します。
これらの演算子を使って、リストを操作し、組み合わせることができます。
リストの仕様
[編集]リスト( list )は、任意のオブジェクトをゼロ個以上、順次付けて保持できるコレクションです[1]。
リストリテラル
[編集]- リストリテラル
print(f"""\ {[]=} {list()=} {list((1,2,3))=} {list(i for i in range(5))=} {[10,"ABC"]=} {[[1,"one"], [2,"two"],[3,"three"]]=} {[ [1,"壱"], [2,"弐"], [3,"参"] ]=} """)
- 実行結果
[]=[] list()=[] list((1,2,3))=[1, 2, 3] list(i for i in range(5))=[0, 1, 2, 3, 4] [10,"ABC"]=[10, 'ABC'] [[1,"one"], [2,"two"],[3,"three"]]=[[1, 'one'], [2, 'two'], [3, 'three']] [ [1,"壱"], [2,"弐"], [3,"参"] ]=[[1, '壱'], [2, '弐'], [3, '参']]
リストは、要素を ,(カンマ) で区切り全体を [ ] で囲みます。 要素の型は同じである必要はありません。
リストと演算子
[編集]- リストと演算子
li = [10 ,"ABC" ,30] print(f'''\ {li=} {li[1]=} {li[-1]=} {li + [2,3,4]=} {li * 2=} {2 * li=} {li == [10 ,"ABC" ,30]=} {li != [10 ,"ABC" ,30]=} {li < [10 ,"ABC" ,30]=} {li > [10 ,"ABC" ,30]=} ''')
- 実行結果
li=[10, 'ABC', 30] li[1]='ABC' li[-1]=30 li + [2,3,4]=[10, 'ABC', 30, 2, 3, 4] li * 2=[10, 'ABC', 30, 10, 'ABC', 30] 2 * li=[10, 'ABC', 30, 10, 'ABC', 30] li == [10 ,"ABC" ,30]=True li != [10 ,"ABC" ,30]=False li < [10 ,"ABC" ,30]=False li > [10 ,"ABC" ,30]=False
- リストの要素は、インデックス演算子で参照できます。
- リスト内の要素の順位はタプルやレンジと同じく、0番から始まります。
- 負のインデクスiは、
len(self)+i
を表します。 - リスト同士の足し算は、連結した新しいリストを返します。
- リストtと整数nとの乗算は、tをn回繰り返したリストを返します。
- 整数nとリストtとの乗算は、tをn回繰り返したリストを返します。
- リスト同士は、比較や大小判別ができます。
リストはミュータブル
[編集]リストの各要素を、代入・置き換えすることもできます。
myList = [10 ,"ABC" ,30] myList[0] = 4 print (myList)
- 実行結果
[4, 'ABC', 30]
- です。「10」が「4」に置き換わっています。
多次元リスト
[編集]リストの中にリストを入れることも出来ます。ただし、下記のように入れたリストの項目数が等しくなるようにする必要があります。
リストの中にリストを入れたものを2次元リスト(または2重リスト)といい、
リストの中にリストを入れたもののなかに、さらにリストを入れたものを3次元リストと言います。
- 二次元リストのコード例
carList = [ ["山田" , "red" , 1234 ] , ["伊藤" , "blue" , 555 ] ] print(carList[0][0] ) print(carList[0][1] ) print(carList[1][0] )
- 実行結果
山田 red 伊藤
map関数
[編集]組込み関数mapを使うと、iterableオブジェクトの全ての要素に、一括で何かの関数を適用する事ができます。
- 関数宣言
map(function, iterable)
- コード例
myList = [-7 , -2, 5] print(f'''\ {myList=} {map(abs, myList)=} {list(map(abs, myList))=} {list(abs(x) for x in myList)=} {[abs(x) for x in myList]=} {[-x if x < 0 else x for x in myList]=} ''')
- 実行結果
myList=[-7, -2, 5] map(abs, myList)=<map object at 0x149ab6e4c0d0> list(map(abs, myList))=[7, 2, 5] list(abs(x) for x in myList)=[7, 2, 5] [abs(x) for x in myList]=[7, 2, 5] [-x if x < 0 else x for x in myList]=[7, 2, 5]
- リスト myList の要素の絶対値を得るプログラムです。
- map関数の第一引数は関数が要求されますが、1つの引数を取り値を帰っす必要があります。ここでは組込み関数absを使いました。
- map関数はリスト...ではなく map object を返します。
- map objectはリストコンストラクタであるlist関数でリスト化できます。
- map関数はジェネレーター式
(function(x) for x in iterable)
と等価です。 - またリスト化するなら、リスト内包表記
[function(x) for x in iterable]
と等価です。 - 内包表記であれば、absの呼出しは条件演算子
-x if x < 0 else x
で置換える事ができます。
abs のような組込み関数だけでなく、ユーザー定義関数やlambdaもmap関数の第一引数にすることができます。
filter関数
[編集]組込み関数filterは、iterableオブジェクトの要素の中から、条件に適合するものだけを選び出して、新たなリストを作ります、
- 関数宣言
filter(function, iterable)
- 引数
-
- function
- 残すかの条件関数False以外を返すと残す
- iterable
- 対処とするiterableオブジェクト
- コード例
myList = [5, 2, 8, 3, 6, 1] print(f'''\ {myList=} {filter(lambda x:x >= 3, myList)=} {list(filter(lambda x:x >= 3, myList))=} {list(x for x in myList if x >= 3)=} {[x for x in myList if x >= 3]=} ''')
- 実行結果
myList=[5, 2, 8, 3, 6, 1] filter(lambda x:x >= 3, myList)=<filter object at 0x154a32dccd00> list(filter(lambda x:x >= 3, myList))=[5, 8, 3, 6] list(x for x in myList if x >= 3)=[5, 8, 3, 6] [x for x in myList if x >= 3]=[5, 8, 3, 6]
- リスト myList から3より多い要素を残すプログラムです。
- filter関数の第一引数は関数を要求されますが、名前は不要で繰返し使う予定もないので lambda を使いました。
- filter関数はリスト...ではなく filter object を返します。
- filter objectはリストコンストラクタであるlist関数でリスト化できます。
- filter関数はジェネレーター式
(x for x in iterable if function(x))
と等価です。 - またリスト化するなら、リスト内包表記
[x for x in iterable if function(x)]
と等価です。
filter関数の第一引数をNoneとした場合
[編集]- コード例
myList = [5, set(), 8, "", 3, False, 6, None, 1, tuple(), 0, 3, []] print(f'''\ {myList=} {filter(None, myList)=} {list(filter(None, myList))=} {list(x for x in myList if x)=} {[x for x in myList if x]=} ''')
- 実行結果
myList=[5, set(), 8, '', 3, False, 6, None, 1, (), 3, []] filter(None, myList)=<filter object at 0x1514a15ee0d0> list(filter(None, myList))=[5, 8, 3, 6, 1, 3] list(x for x in myList if x)=[5, 8, 3, 6, 1, 3] [x for x in myList if x]=[5, 8, 3, 6, 1, 3]
- リスト myList からfalsy[2]でない要素を残すプログラムです。
- filter関数の第一引数は関数を要求されますが、Noneを渡すとfalsyな要素を除去します。
- この場合も、filter関数はリスト...ではなく filter object を返します。
- この場合も、filter objectはリストコンストラクタであるlist関数でリスト化できます。
- この場合は、filter関数はジェネレーター式
(x for x in iterable if x)
と等価です。 - この場合はリスト化するなら、リスト内包表記
[x for x in iterable if x]
と等価です。
リスト内包表記を使った例
[編集]上記のmap関数とfilter関数の使用例はリスト内包表記をつかうと
- コード例
myList = [-7 , -2, 5] obj = [abs(i) for i in myList] print(obj) myList = [5, 2, 8, 6, 1] obj = [i for i in myList if i >= 3] print(obj)
と表現できます。 for式やif式、if-else式(条件演算子)はリスト内包表記と組合わせると関数呼出しを使わないでもイテレーションやケース分けができます。
絶対値を求める部分も、
obj = [-i if i < 0 else i for i in myList]
とインラインで表現できます。
リストのフィールド一覧
[編集]- リストのフィールド一覧
obj = [] for i in dir(obj): print(i, eval(f"type({obj}.{i})"))
- 実行結果
__add__ <class 'method-wrapper'> __class__ <class 'type'> __contains__ <class 'method-wrapper'> __delattr__ <class 'method-wrapper'> __delitem__ <class 'method-wrapper'> __dir__ <class 'builtin_function_or_method'> __doc__ <class 'str'> __eq__ <class 'method-wrapper'> __format__ <class 'builtin_function_or_method'> __ge__ <class 'method-wrapper'> __getattribute__ <class 'method-wrapper'> __getitem__ <class 'builtin_function_or_method'> __gt__ <class 'method-wrapper'> __hash__ <class 'NoneType'> __iadd__ <class 'method-wrapper'> __imul__ <class 'method-wrapper'> __init__ <class 'method-wrapper'> __init_subclass__ <class 'builtin_function_or_method'> __iter__ <class 'method-wrapper'> __le__ <class 'method-wrapper'> __len__ <class 'method-wrapper'> __lt__ <class 'method-wrapper'> __mul__ <class 'method-wrapper'> __ne__ <class 'method-wrapper'> __new__ <class 'builtin_function_or_method'> __reduce__ <class 'builtin_function_or_method'> __reduce_ex__ <class 'builtin_function_or_method'> __repr__ <class 'method-wrapper'> __reversed__ <class 'builtin_function_or_method'> __rmul__ <class 'method-wrapper'> __setattr__ <class 'method-wrapper'> __setitem__ <class 'method-wrapper'> __sizeof__ <class 'builtin_function_or_method'> __str__ <class 'method-wrapper'> __subclasshook__ <class 'builtin_function_or_method'> append <class 'builtin_function_or_method'> clear <class 'builtin_function_or_method'> copy <class 'builtin_function_or_method'> count <class 'builtin_function_or_method'> extend <class 'builtin_function_or_method'> index <class 'builtin_function_or_method'> insert <class 'builtin_function_or_method'> pop <class 'builtin_function_or_method'> remove <class 'builtin_function_or_method'> reverse <class 'builtin_function_or_method'> sort <class 'builtin_function_or_method'>
リストと演算子
[編集]- リストと演算子
print(f'''\ {[1,2,3] + [7,8,9] =} {[1,2,3] * 2 =} {2 in [1,2,3] =} {[1,2,3] == [7,8,9] =} {[1,2,3] == [1,2,3] =} {[1,2,3] != [7,8,9] =} {[1,2,3] != [1,2,3] =} {[1,2,3] > [1,2] =} {[1,2,3] < [1,2] =} ''') import operator print(f'''\ {operator.__add__([1,2,3], [7,8,9]) =} {operator.__mul__([1,2,3], 2) =} {operator.__contains__([1,2,3],2)=} {operator.__eq__([1,2,3], [7,8,9]) =} {operator.__eq__([1,2,3], [1,2,3]) =} {operator.__ne__([1,2,3], [7,8,9]) =} {operator.__ne__([1,2,3], [1,2,3]) =} {operator.__gt__([1,2,3], [1,2]) =} {operator.__lt__([1,2,3], [1,2]) =} ''') print(", ".join(vars(operator)))
- 実行結果
[1,2,3] + [7,8,9] =[1, 2, 3, 7, 8, 9] [1,2,3] * 2 =[1, 2, 3, 1, 2, 3] 2 in [1,2,3] =True [1,2,3] == [7,8,9] =False [1,2,3] == [1,2,3] =True [1,2,3] != [7,8,9] =True [1,2,3] != [1,2,3] =False [1,2,3] > [1,2] =True [1,2,3] < [1,2] =False operator.__add__([1,2,3], [7,8,9]) =[1, 2, 3, 7, 8, 9] operator.__mul__([1,2,3], 2) =[1, 2, 3, 1, 2, 3] operator.__contains__([1,2,3],2)=True operator.__eq__([1,2,3], [7,8,9]) =False operator.__eq__([1,2,3], [1,2,3]) =True operator.__ne__([1,2,3], [7,8,9]) =True operator.__ne__([1,2,3], [1,2,3]) =False operator.__gt__([1,2,3], [1,2]) =True operator.__lt__([1,2,3], [1,2]) =False __name__, __doc__, __package__, __loader__, __spec__, __file__, __cached__, __builtins__, __all__, _abs, lt, le, eq, ne, ge, gt, not_, truth, is_, is_not, abs, add, and_, floordiv, index, inv, invert, lshift, mod, mul, matmul, neg, or_, pos, pow, rshift, sub, truediv, xor, concat, contains, countOf, delitem, getitem, indexOf, setitem, length_hint, attrgetter, itemgetter, methodcaller, iadd, iand, iconcat, ifloordiv, ilshift, imod, imul, imatmul, ior, ipow, irshift, isub, itruediv, ixor, __lt__, __le__, __eq__, __ne__, __ge__, __gt__, __not__, __abs__, __add__, __and__, __floordiv__, __index__, __inv__, __invert__, __lshift__, __mod__, __mul__, __matmul__, __neg__, __or__, __pos__, __pow__, __rshift__, __sub__, __truediv__, __xor__, __concat__, __contains__, __delitem__, __getitem__, __setitem__, __iadd__, __iand__, __iconcat__, __ifloordiv__, __ilshift__, __imod__, __imul__, __imatmul__, __ior__, __ipow__, __irshift__, __isub__, __itruediv__, __ixor__
- モジュールoperatorを使うと、演算子を関数形式で呼び出すことができます[3]。
他のプログラミング言語との比較
[編集]他のプログラミング言語とPythonの類似点と差異をリストを中心に比較します。
- Python
compound = [ 10, 20, 30 ]
- Ruby
compound = [ 10, 20, 30 ]
- 完全に一致
- JavaScript
let compound = [ 10, 20, 30 ]
- let があること以外同じ
- JavaScript(TypedArray)
let compound = new Int32Array([10,20,30])
- ECMAScript 2015(ES6)でTypedArray(型付き配列)が追加されました。
- TypedArrayはJSの配列とは違い、単一要素型で連続したメモリーに割当てられます。
- C言語
int compound[] = { 10, 20, 30 };
- だいぶ違う
- 意味的にも、C言語の配列は全ての要素の型は同一で連続したメモリーに割り付けられます。
- Go(配列)
compound := [...]int{ 10, 20, 30 }
- C言語ともだいぶ違う
- 意味的には、C言語の配列と同じく全ての要素の型は同一で連続したメモリーに割り付けられます。
- Go(スライス)
compound := []int{ 10, 20, 30 }
- よく似た構文ですが [ ] の中に ... がないのはスライス
- スライスの要素は離散的なアドレスに配置され、動的に長さ(要素数)の変更が可能です。
宣言と初期化の部分に注目し様々な差異がありましたが、要素の参照は、
- Python
compound[1]
の構文で、この部分はどの言語でもほぼ同じですが、FortranとBASICでは、
- Fortran, BASIC
compound(1)
のように丸括弧になります。
- それぞれの言語のリストに似た型
Pythonに「配列」というデータ型は存在しません[4]。C言語などに、配列というデータ型があります。
言語によっては、「配列」データ型と「リスト」データ型とが別個に存在するものもあります(たとえば Kotlin という言語には、配列(array)データ型と、リスト list データ型とが別々に存在します) なお、kotlin は現在では、Android スマートホンのアプリケーションプログラムの開発などで、よく使われる言語です。
また、Goには「リスト」はなく「スライス」slice があります(Goのスライスの機能はPythonやkotlinの「リスト」と一見似ていますが、Goのスライスは「要素の型が一致している必要がある」ので本質的に「リスト」とは違い、異種リストの実装には interface{} を使います)。
Goには、配列型と「スライス」slice の2つのデータ型がありよく混同されますが、スライスは要素のアクセスは線形時間 O(n)、配列の要素のアクセスは定数時間 O(1)であることが大きな違いです。
要素の参照速度による分類
[編集]リストや配列に類似した型は、要素の参照にかかる時間によって
- 線形時間 O(n)が必要なもの
- Pythonのリスト、Goのスライスはこれに当たります
- 個々の要素の型は異なっても良い
- 要素数の増減可能
- 定数時間 O(1)で済むもの
- Pythonの標準モジュールの array や拡張モジュール NumPy、JavaScriptのTypedArray、C言語の配列、Goの配列
- 個々の要素の型は一致している必要がある
- 要素数は宣言時に確定する
- 宣言時の要素数に定数式しか受け付けない言語(過去のC言語やGo)と、宣言時の要素数に実行時まで確定しない式も受け付ける言語(現在のC言語など)がある
- ^ “3.10.1 Documentation » The Python Language Reference » 3. Data model ¶3.2. The standard type hierarchy” (2021年12月16日). 2021年12月16日閲覧。
- ^ falsy: 組込み関数bool() に与えると False を返すような式。False, None の他、空集合(set())、空文字列()、0、空タプル(tuple())、空リスト([])など
- ^ “operator — Standard operators as functions — Python 3.10.1 documentation” (2021年12月15日). 2021年12月15日閲覧。
- ^ 標準モジュールの array あるいは、拡張モジュールの NumPy で連続した領域に要素が配置される配列が提供されますが、組込みオブジェクトの配列はありません。