ユーニックス総合研究所

  • home
  • archives
  • python-array-init

Pythonの配列の初期化はアスタリスクを使います

  • 作成日: 2022-04-06
  • 更新日: 2023-12-25
  • カテゴリ: Python

Pythonの配列の初期化方法

Pythonでは配列(リスト、list)を使うことができます。
この配列を初期化する方法を今回は解説します。

配列を初期化できるようになると、Pythonによるコーディングの幅が広がります。
キーワードは「アスタリスク」です。

関連記事

頭が悪い人のPythonのevalの使い方
頭がいい人のPythonのexitの使い方
状態遷移による文字列パースのテクニック【Python】

頭が悪い人のPythonのevalの使い方
頭がいい人のPythonのexitの使い方

アスタリスクを使った配列の初期化

Pythonの配列に*(アスタリスク)で数値をかけると、初期化された配列を作成できます。

l = [0] * 3  

print(l)  # [0, 0, 0]  

↑のように0クリアされた配列を作成できます。
パターン化された数値の列を繰り返したい場合もこの方法が使えます。

l = [0, 1, 2] * 3  

print(l)  # [0, 1, 2, 0, 1, 2, 0, 1, 2]  

入れ子の配列の初期化

入れ子になった配列の初期化でアスタリスクを使うとどうなるのでしょうか。
たとえば↓のようにです。

l = [[0, 1, 2]] * 3  

print(l)  # [[0, 1, 2], [0, 1, 2], [0, 1, 2]]  

↑のように書くと入れ子の行列を作成できますが、一見するとうまくいってるように見えます。
しかしこの作成方法だと、内部の配列がすべて同じものになってしまいます。

l[0][0] = 9  

print(l)  # [[9, 1, 2], [9, 1, 2], [9, 1, 2]]  

↑の場合、l[0][0]9を代入してますが、内側のすべての配列の0番目の要素が書き換えられています。
これは入れ子の内部の配列がすべてメモリ上で同じものだからです。

このようなトラブルを無くすにはリスト内包表記を使います。

l = [[0, 1, 2] for i in range(3)]  
l[0][0] = 9  

print(l)  # [[9, 1, 2], [0, 1, 2], [0, 1, 2]]  

↑のようにリスト内包表記を使うと内部の配列のメモリは共有されません。

rangeを使った配列の初期化

list()range()を渡すと数列を生成できます。

l = list(range(3))  

print(l)  # [0, 1, 2]  

リスト内包表記を使った配列の初期化

リスト内包表記でも数列を持った配列に初期化できます。

l = [i for i in range(3)]  

print(l)  # [0, 1, 2]  

また単純に0クリアすることもできます。

l = [0 for _ in range(3)]  

print(l)  # [0, 0, 0]  

配列初期化用の関数を作る

配列初期化用の関数を作っておくと、アルゴリズムの交換ができるようになります。
たとえばgenaryという初期化用関数を作ります。

def genary(val, size):  
    return [val] * size  

l = genary(0, 3)  

print(l)  # [0, 0, 0]  

このような関数を作っておくと配列初期化のアルゴリズムを後から交換することも出来ます。
たとえば↓のようにappendを使った実装に変更します。

def genary2(val, size):  
    l = []  
    for _ in range(size):  
        l.append(val)  
    return l  

l = genary2(0, 3)  

print(l)  # [0, 0, 0]  

理屈ではこのように関数でラップしたほうが柔軟性が上がりますが、じっさいはこういった関数は使わずにマジックナンバー的に配列の初期化を書くことが多いと思います。

で、どれが一番早いの?

計測結果は環境によって変わることがあるので、あくまで目安ですが、↓のコードで速度を計測しました。
テスト時の環境はWindows10(64ビット)、Windows版Python3.9.2です。

import time  


n = 50000000  


# アスタリスク  
start = time.time()  

l = [0] * n  

tm = time.time() - start  
print('アスタリスク', tm, '秒')  


# リスト内包表記  
start = time.time()  

l = [0 for _ in range(n)]  

tm = time.time() - start  
print('リスト内包表記', tm, '秒')  


# range  
start = time.time()  

l = list(range(n))  

tm = time.time() - start  
print('range', tm, '秒')  


# append  
start = time.time()  

l = []  
for _ in range(n):  
    l.append(0)  

tm = time.time() - start  
print('append', tm, '秒')  
アスタリスク 0.10000038146972656 秒  
リスト内包表記 1.7260305881500244 秒  
range 0.7280459403991699 秒  
append 4.059716463088989 秒  

この結果を見ると一番早いのはアスタリスクを使った0クリアです。
一番遅いのはappendを使った方法ですね。
これはめちゃくちゃ遅いみたいです。

*テスト環境によってテスト結果は変わります。
*たとえばWindowsとLinuxでは結果が異なる場合があります。

おわりに

今回はPythonの配列の初期化方法を解説しました。
アスタリスクを使った初期化は高速ですが入れ子の配列に使う場合は注意が必要です。

🦝 < 初期化するぜよ

🐭 < 配列を準備しよう