有用的冷门新知识:为什么python语言的列表推导式比循环性能好

258 阅读3分钟

列表推导式 vs. 循环:Python 中创建列表的两种方法

在 Python 中,列表推导式和循环都可以用来创建列表,但它们在写法、用途、效率和可读性上有所不同。简单来说,列表推导式更简洁高效,而循环更灵活。

1. 写法 (Syntax)

  • 列表推导式: 像一个公式,把创建列表的逻辑写在一行里。 [结果表达式 for 变量 in 可迭代对象 if 条件] 例如,创建一个包含 1 到 10 的平方的列表:[x**2 for x in range(1, 11)]

  • 循环: 像一段代码,需要多行来完成。

    结果列表 = []
    for 变量 in 可迭代对象:
        if 条件:
            结果列表.append(结果表达式)
    

    例如,用循环创建包含 1 到 10 的平方的列表:

    result = []
    for x in range(1, 11):
        result.append(x**2)
    

2. 用途 (Usage)

  • 列表推导式: 主要用于快速生成新列表,特别是当新列表的元素可以通过简单的计算和筛选得到时。 适合于转换现有列表或者生成符合特定规则的列表。
  • 循环: 用途更广,可以做任何需要迭代的事情,比如读取文件、处理数据等等。 不仅限于创建列表。

3. 效率 (Performance)

  • 通常,列表推导式比循环更快。 这是因为列表推导式在 Python 内部进行了优化。

  • 例子: 创建一个包含 1 到 10000 的平方的列表,列表推导式大约快 30%-50%。

    import time
    
    # 使用 for 循环
    def using_for_loop():
        result = []
        for i in range(1, 10001):
            result.append(i ** 2)
        return result
    
    # 使用列表推导式
    def using_list_comprehension():
        return [i ** 2 for i in range(1, 10001)]
    
    # 测量 for 循环的时间
    start_time = time.time()
    using_for_loop()
    for_loop_time = time.time() - start_time
    
    # 测量列表推导式的时间
    start_time = time.time()
    using_list_comprehension()
    list_comprehension_time = time.time() - start_time
    
    print(f"For 循环耗时: {for_loop_time:.4f} 秒")
    print(f"列表推导式耗时: {list_comprehension_time:.4f} 秒")
    

    运行结果示例:

    For 循环耗时: 0.0025 秒
    列表推导式耗时: 0.0017 秒
    

4. 可读性 (Readability)

  • 列表推导式: 对于简单的逻辑,更易读。可以很直观地表达“对每个元素,如果满足条件,就进行处理并添加到新列表”。
  • 循环: 对于复杂的逻辑,可能更清晰。可以将逻辑分解成小块,并用变量名解释每一步的目的。

实际应用例子

  • 数据清洗: 从一个包含字符串的列表中,提取所有长度大于 5 的字符串,并转换为大写。

    # 使用列表推导式
    strings = ["apple", "banana", "kiwi", "orange", "grape"]
    long_upper_strings = [s.upper() for s in strings if len(s) > 5]
    print(long_upper_strings)  # 输出:['BANANA', 'ORANGE']
    
    # 使用循环
    strings = ["apple", "banana", "kiwi", "orange", "grape"]
    long_upper_strings = []
    for s in strings:
        if len(s) > 5:
            long_upper_strings.append(s.upper())
    print(long_upper_strings)  # 输出:['BANANA', 'ORANGE']
    
  • 生成特定格式的数据: 从一个包含学生信息的字典列表中,提取所有学生的姓名和年龄,并生成一个新的列表,其中每个元素是一个 "姓名-年龄" 格式的字符串。

    # 使用列表推导式
    students = [
        {"name": "张三", "age": 18},
        {"name": "李四", "age": 20},
        {"name": "王五", "age": 19}
    ]
    name_age_list = [f"{s['name']}-{s['age']}" for s in students]
    print(name_age_list)  # 输出:['张三-18', '李四-20', '王五-19']
    
    # 使用循环
    students = [
        {"name": "张三", "age": 18},
        {"name": "李四", "age": 20},
        {"name": "王五", "age": 19}
    ]
    name_age_list = []
    for s in students:
        name_age_list.append(f"{s['name']}-{s['age']}")
    print(name_age_list)  # 输出:['张三-18', '李四-20', '王五-19']
    

总结

列表推导式更简洁、可读,通常也更快。但对于非常复杂的逻辑,使用循环可能更合适。 选择哪种方式取决于具体情况,根据逻辑的复杂度和对性能的要求来决定。一般来说,简单的列表生成任务,优先使用列表推导式。