Last Updated: 2/6/2024, 5:44:57 AM

# 4.1. リストの初期化

for 文の方が速い

# 4.1.1. 比較対象のコード

def multicative_list(n):
    lst = [None] * n * n
    return lst


def for_statement(n):
    lst = []
    for i in range(n * n):
        lst.append(None)
    return lst


def for_statement_list_comprehension(n):
    lst = [None for i in range(n * n)]
    return lst


def while_statement(n):
    lst = []
    i = 0
    while i < n * n:
        lst.append(None)
        i += 1
    return lst


def while_statement_with_iterator(n):
    lst = []
    iterator = iter(range(n * n))
    while True:
        try:
            next(iterator)
        except StopIteration:
            break
        lst.append(None)
    return lst


def while_statement_with_iterator_optimized(n):
    lst = []
    iterator = iter(range(n * n))
    next_ = iterator.__next__
    append = lst.append
    while True:
        try:
            next_()
        except StopIteration:
            break
        append(None)
    return lst

# 4.1.2. 測定結果

$ python 4_1_list_initialization.py 

# Case 0
# (10**0, )
multicative_list                         :   0.0003 [msec]
for_statement                            :   0.0007 [msec]
for_statement_list_comprehension         :   0.0007 [msec]
while_statement                          :   0.0003 [msec]
while_statement_with_iterator            :   0.0015 [msec]
while_statement_with_iterator_optimized  :   0.0015 [msec]

# Case 1
# (10**1, )
multicative_list                         :   0.0009 [msec]
for_statement                            :   0.0091 [msec]
for_statement_list_comprehension         :   0.0042 [msec]
while_statement                          :   0.0157 [msec]
while_statement_with_iterator            :   0.0177 [msec]
while_statement_with_iterator_optimized  :   0.0121 [msec]

# Case 2
# (10**2, )
multicative_list                         :   0.0406 [msec]
for_statement                            :   0.9463 [msec]
for_statement_list_comprehension         :   0.4387 [msec]
while_statement                          :   1.8476 [msec]
while_statement_with_iterator            :   1.8201 [msec]
while_statement_with_iterator_optimized  :   1.1436 [msec]

# Case 3
# (10**3, )
multicative_list                         :   4.5784 [msec]
for_statement                            : 100.6129 [msec]
for_statement_list_comprehension         :  47.8807 [msec]
while_statement                          : 198.1089 [msec]
while_statement_with_iterator            : 180.4927 [msec]
while_statement_with_iterator_optimized  : 119.8062 [msec]

# 4.1.3. 補足

単純に初期化したいだけなら、掛け算 [None] * n が一番速い。

2, 3. for statement は 4, 5, 6. while statement より速い。

3. list comprehension は 2. for statement より速い。

# 4.1.3.1. while statement with iterator (optimized) について

頑張って while 文を速くしようしました。 それでも、どうあがいても for 文よりも while 文を速くできませんでした。適当に読み飛ばしてください。

6. while statement with iterator (optimized) は 4. while statement に 3 つの工夫を加えています。

1 つ目は while statement による条件の判定を無くしました。 while i < 3000*3000: は都度、条件を判定しているので、 これを iterator を使った例外処理に置き換えています。 置き換えたものが 5. while statement with iterator になります。 しかし、 4 よりも 5 の方が遅くなっていますね。そこでさらにもう2つの工夫を加えます。

2 つ目の工夫は、関数呼び出しのコストを削っています。 通常 iterator は 5. while statement with iterator にあるように next(iterator) として使います。 しかし、ここでは next 関数は iterator.__next__ メソッドを呼び出しているだけです。 そこで直接 iterator.__next__ メソッドを呼び出して next 関数を呼び出しのコストを削っています。

3 つ目の工夫は、属性の参照のコストを削っています。 通常メソッドの呼び出しは obj.method(parameters) です。 これを method=obj.method として method(parameters) で呼び出せるようにします。