【Python】For 循环相关
2022年 09月 13 日

子弹

1. 列表表达式和生成器

要从一个可迭代对象中取数据建立一个 list

from timeit import timeit

def with_for():
    lst = []
    for i in range(1000):
        lst.append(i)
    return lst

def without_for():
    return [i for i in range(1000)]

print(f"with:    {timeit(with_for, number=10000)}")
print(f"without:{timeit(without_for, number=10000)}")

运行结果

with:   0.303983400001016
without:0.16779089999909047

可以看到列表表达式要 For 循环快将近一倍

最大的影响因素就是这个 append 函数,在做 lst.append() 时,python 没有办法直接判断你使用的就是列表的 append 的函数。所以想要从 lst 中找到 append 这个函数再拿出来,再调用它。而当使用列表表达式的时候,python 就可以直接去调用那个列表的 append 函数了。

[] 改成 () 就得到了生成器,由于没有建立这个列表,而是建立了一个生成器,这个操作比列表表达式还要快非常多。

from timeit import timeit

def with_for():
    lst = []
    for i in range(1000):
        lst.append(i)
    return lst

def without_for():
    return (i for i in range(1000))

print(f"with:    {timeit(with_for, number=10000)}")
print(f"without:{timeit(without_for, number=10000)}")

结果

with:   0.3137756999967678
without:0.0028984999989916105

2. max() 和 min()

这两个函数分别是求可迭代对象中的最大值和最小值

from timeit import timeit

lst = [i for i in range(100)]

def with_for():
    max_num = 0
    for num in lst:
        if num > max_num:
            max_num = num
    return max_num

def without_for():
    return max(lst)

print(f"with:    {timeit(with_for, number=10000)}")
print(f"without:{timeit(without_for, number=10000)}")

结果

with:   0.021164999998291023
without:0.0069537999988824595

能用 bulletin 完成的代码,不要用 python 写

3. any() 和 all()

3.1 any()

找遍一个列表,如果发现一个什么样的东西直接返回 True,否则的话返回 False

比如查找列表中有没有大于 50 的数

from timeit import timeit

lst = [i for i in range(100)]

def with_for():
    for num in lst:
        if num > 50:
            return True
    return False

def without_for():
    return any(num > 50 for num in lst)

print(f"with:    {timeit(with_for, number=10000)}")
print(f"without:{timeit(without_for, number=10000)}")

结果

with:   0.009332400000857888
without:0.019502699997246964

运行后发现使用 any() 会比直接写 python 还要慢一些,这里的原因是生成器的本身还是运行在 python 层面的,而生成器的建立调用本身是有代价的,所以使用 any() 的时候反而更慢了 。事实上如果我们没有这个生成器,而是直接在一个列表里找 True 的话,any() 要比 python 的写法更快的。

3.2 all()

当要判断一个可迭代对象里面是不是全都是 True 的时候,可以使用 all()

from timeit import timeit

lst = [i for i in range(100)]

def with_for():
    for num in lst:
        if num > 100:
            return False
    return True

def without_for():
    return all(num <= 100 for num in lst)

print(f"with:    {timeit(with_for, number=10000)}")
print(f"without:{timeit(without_for, number=10000)}")

结果

with:   0.015045099997223588
without:0.033781900001486065

当我们在使用 any() 或者 all() 的时候,要使用生成器而不用列表表达式

4. filter()

用第一个函数来判断这个值要不要

from timeit import timeit

lst = [i for i in range(100)]

def good(num):
    return num >= 60

def with_for():
    ret = []
    for num in lst:
        if good(num):
            ret.append(num)
    return ret

def without_for():
    return [filter(good, lst)]

print(f"with:    {timeit(with_for, number=10000)}")
print(f"without:{timeit(without_for, number=10000)}")

结果

with:   0.059730799999670126
without:0.0014754000003449619

5. map()

from timeit import timeit

lst = [i for i in range(100)]

def change(num):
    return num * 2

def with_for():
    ret = []
    for num in lst:
        ret.append(change(num))
    return ret

def without_for():
    # return (change(num) for num in lst)
    return map(change, lst)

print(f"with:    {timeit(with_for, number=10000)}")
print(f"without:{timeit(without_for, number=10000)}")

结果

with:   0.0747945000002801
without:0.0008847999997669831

map() 可以接收多个参数

from timeit import timeit

lst = [i for i in range(100)]
lst2 = [i for i in range(100)]

def change(num, num2):
    return num + num2

def with_for():
    ret = []
    for idx in range(len(lst)):
        ret.append(change(lst[idx], lst2[idx]))
    return ret

def without_for():
    # return (change(lst[idx], lst2[idx]) for i in range(len(lst)))
    return map(change, lst, lst2)

print(f"with:    {timeit(with_for, number=10000)}")
print(f"without:{timeit(without_for, number=10000)}")

结果

with:   0.09803069999907166
without:0.0011946000013267621

6. zip()

from timeit import timeit

lst = [i for i in range(100)]
lst2 = [i for i in range(100)]

def with_for():
    ret = []
    for i in range(len(lst)):
        ret.append((lst[i], lst[1]))
    return ret  # [(0, 0), (1, 1), (2, 2)...]

def without_for():
    return zip(lst, lst2)

print(f"with:    {timeit(with_for, number=10000)}")
print(f"without:{timeit(without_for, number=10000)}")

结果

with:   0.0706549000024097
without:0.0015113999979803339

例子

from timeit import timeit

names = ["Alice", "Bob", "Charlie"]
ages = [18, 16, 19]
scores = [3, 4, 5]

def with_for():
    for i in range(len(names)):
        name = names[i]
        age = age[i]
        score = scores[i]
        print(name, age, score)
        
def without_for():
    for name, age, score in zip(names, ages, scores):
        print(name, age, score)

print(f"with:    {timeit(with_for, number=1)}")
print(f"without:{timeit(without_for, number=1)}")

结果

Alice 18 3
Bob 16 4
Charlie 19 5
with:   0.00031540000054519624
Alice 18 3
Bob 16 4
Charlie 19 5
without:0.0002550999997765757

【Python】For 循环相关

1. 列表表达式和生成器

要从一个可迭代对象中取数据建立一个 list

from timeit import timeit

def with_for():
    lst = []
    for i in range(1000):
        lst.append(i)
    return lst

def without_for():
    return [i for i in range(1000)]

print(f"with:    {timeit(with_for, number=10000)}")
print(f"without:{timeit(without_for, number=10000)}")

运行结果

with:   0.303983400001016
without:0.16779089999909047

可以看到列表表达式要 For 循环快将近一倍

最大的影响因素就是这个 append 函数,在做 lst.append() 时,python 没有办法直接判断你使用的就是列表的 append 的函数。所以想要从 lst 中找到 append 这个函数再拿出来,再调用它。而当使用列表表达式的时候,python 就可以直接去调用那个列表的 append 函数了。

[] 改成 () 就得到了生成器,由于没有建立这个列表,而是建立了一个生成器,这个操作比列表表达式还要快非常多。

from timeit import timeit

def with_for():
    lst = []
    for i in range(1000):
        lst.append(i)
    return lst

def without_for():
    return (i for i in range(1000))

print(f"with:    {timeit(with_for, number=10000)}")
print(f"without:{timeit(without_for, number=10000)}")

结果

with:   0.3137756999967678
without:0.0028984999989916105

2. max() 和 min()

这两个函数分别是求可迭代对象中的最大值和最小值

from timeit import timeit

lst = [i for i in range(100)]

def with_for():
    max_num = 0
    for num in lst:
        if num > max_num:
            max_num = num
    return max_num

def without_for():
    return max(lst)

print(f"with:    {timeit(with_for, number=10000)}")
print(f"without:{timeit(without_for, number=10000)}")

结果

with:   0.021164999998291023
without:0.0069537999988824595

能用 bulletin 完成的代码,不要用 python 写

3. any() 和 all()

3.1 any()

找遍一个列表,如果发现一个什么样的东西直接返回 True,否则的话返回 False

比如查找列表中有没有大于 50 的数

from timeit import timeit

lst = [i for i in range(100)]

def with_for():
    for num in lst:
        if num > 50:
            return True
    return False

def without_for():
    return any(num > 50 for num in lst)

print(f"with:    {timeit(with_for, number=10000)}")
print(f"without:{timeit(without_for, number=10000)}")

结果

with:   0.009332400000857888
without:0.019502699997246964

运行后发现使用 any() 会比直接写 python 还要慢一些,这里的原因是生成器的本身还是运行在 python 层面的,而生成器的建立调用本身是有代价的,所以使用 any() 的时候反而更慢了 。事实上如果我们没有这个生成器,而是直接在一个列表里找 True 的话,any() 要比 python 的写法更快的。

3.2 all()

当要判断一个可迭代对象里面是不是全都是 True 的时候,可以使用 all()

from timeit import timeit

lst = [i for i in range(100)]

def with_for():
    for num in lst:
        if num > 100:
            return False
    return True

def without_for():
    return all(num <= 100 for num in lst)

print(f"with:    {timeit(with_for, number=10000)}")
print(f"without:{timeit(without_for, number=10000)}")

结果

with:   0.015045099997223588
without:0.033781900001486065

当我们在使用 any() 或者 all() 的时候,要使用生成器而不用列表表达式

4. filter()

用第一个函数来判断这个值要不要

from timeit import timeit

lst = [i for i in range(100)]

def good(num):
    return num >= 60

def with_for():
    ret = []
    for num in lst:
        if good(num):
            ret.append(num)
    return ret

def without_for():
    return [filter(good, lst)]

print(f"with:    {timeit(with_for, number=10000)}")
print(f"without:{timeit(without_for, number=10000)}")

结果

with:   0.059730799999670126
without:0.0014754000003449619

5. map()

from timeit import timeit

lst = [i for i in range(100)]

def change(num):
    return num * 2

def with_for():
    ret = []
    for num in lst:
        ret.append(change(num))
    return ret

def without_for():
    # return (change(num) for num in lst)
    return map(change, lst)

print(f"with:    {timeit(with_for, number=10000)}")
print(f"without:{timeit(without_for, number=10000)}")

结果

with:   0.0747945000002801
without:0.0008847999997669831

map() 可以接收多个参数

from timeit import timeit

lst = [i for i in range(100)]
lst2 = [i for i in range(100)]

def change(num, num2):
    return num + num2

def with_for():
    ret = []
    for idx in range(len(lst)):
        ret.append(change(lst[idx], lst2[idx]))
    return ret

def without_for():
    # return (change(lst[idx], lst2[idx]) for i in range(len(lst)))
    return map(change, lst, lst2)

print(f"with:    {timeit(with_for, number=10000)}")
print(f"without:{timeit(without_for, number=10000)}")

结果

with:   0.09803069999907166
without:0.0011946000013267621

6. zip()

from timeit import timeit

lst = [i for i in range(100)]
lst2 = [i for i in range(100)]

def with_for():
    ret = []
    for i in range(len(lst)):
        ret.append((lst[i], lst[1]))
    return ret  # [(0, 0), (1, 1), (2, 2)...]

def without_for():
    return zip(lst, lst2)

print(f"with:    {timeit(with_for, number=10000)}")
print(f"without:{timeit(without_for, number=10000)}")

结果

with:   0.0706549000024097
without:0.0015113999979803339

例子

from timeit import timeit

names = ["Alice", "Bob", "Charlie"]
ages = [18, 16, 19]
scores = [3, 4, 5]

def with_for():
    for i in range(len(names)):
        name = names[i]
        age = age[i]
        score = scores[i]
        print(name, age, score)
        
def without_for():
    for name, age, score in zip(names, ages, scores):
        print(name, age, score)

print(f"with:    {timeit(with_for, number=1)}")
print(f"without:{timeit(without_for, number=1)}")

结果

Alice 18 3
Bob 16 4
Charlie 19 5
with:   0.00031540000054519624
Alice 18 3
Bob 16 4
Charlie 19 5
without:0.0002550999997765757

赞 (2)

评论区(暂无评论)

这里空空如也,快来评论吧~

我要评论