pin_drop当前位置:知识文库 ❯ 图文
Python reversed sorted sum函数
目录
一、reversed()反向迭代器
reversed() 是Python内置函数,用于创建一个反向迭代器。它不会修改原序列,而是返回一个迭代器,按逆序遍历元素。适用于列表、元组、字符串和任何实现了 __reversed__() 或 __getitem__() 和 __len__() 的对象。
示例1:基本用法
代码示例
# 列表反转
numbers = [1, 2, 3, 4, 5]
rev_iter = reversed(numbers)
print(f"原列表: {numbers}")
print(f"反向迭代器: {list(rev_iter)}")
# 直接在for循环中使用
print("倒序遍历:")
for num in reversed(numbers):
print(num, end=" ")
# 输出: 5 4 3 2 1
# 输出结果
# 原列表: [1, 2, 3, 4, 5]
# 反向迭代器: [5, 4, 3, 2, 1]
# 倒序遍历:
# 5 4 3 2 1
示例2:字符串和元组
代码示例
# 字符串反转
text = "Python"
reversed_text = "".join(reversed(text))
print(f"原字符串: {text}")
print(f"反转后: {reversed_text}")
# 元组反转
tup = (10, 20, 30, 40)
reversed_tup = tuple(reversed(tup))
print(f"原元组: {tup}")
print(f"反转后: {reversed_tup}")
# 输出结果
# 原字符串: Python
# 反转后: nohtyP
# 原元组: (10, 20, 30, 40)
# 反转后: (40, 30, 20, 10)
二、reversed()与切片[::-1]对比
Python中反转序列有两种常见方式:reversed() 和切片 [::-1]。两者在使用场景和性能上有所不同。
示例1:性能对比
代码示例
import time
data = list(range(1000000))
# 方式1:reversed() - 返回迭代器,惰性求值
start = time.time()
rev1 = reversed(data)
# 只创建迭代器,不立即复制数据
time1 = time.time() - start
print(f"reversed()创建时间: {time1:.6f}秒")
# 方式2:切片[::-1] - 创建新列表
start = time.time()
rev2 = data[::-1]
# 立即复制整个列表
time2 = time.time() - start
print(f"切片[::-1]创建时间: {time2:.6f}秒")
print(f"结果相同: {list(rev1) == rev2}")
# 输出结果(因机器而异)
# reversed()创建时间: 0.000001秒(极快)
# 切片[::-1]创建时间: 0.012345秒(需要复制)
# 结果相同: True
提示:如果只是遍历而不需要新列表,优先使用
reversed(),因为它返回迭代器,内存效率更高。如果需要一个新的反转列表,使用切片[::-1]更简洁。
三、sorted()排序函数
sorted() 是Python内置的排序函数,对任意可迭代对象进行排序并返回新的列表。与列表的 sort() 方法不同,sorted()不会修改原对象,而是返回一个排序后的新列表。
代码示例
# sorted()函数语法
sorted(iterable, key=None, reverse=False)
# 参数说明:
# iterable - 可迭代对象
# key - 可选,自定义排序规则函数
# reverse - 可选,是否降序(默认False为升序)
示例1:基础排序
代码示例
# 数字排序
numbers = [64, 34, 25, 12, 22, 11, 90]
sorted_numbers = sorted(numbers)
print(f"原列表: {numbers}")
print(f"升序排序: {sorted_numbers}")
print(f"原列表未修改: {numbers}")
# 降序排序
desc_numbers = sorted(numbers, reverse=True)
print(f"降序排序: {desc_numbers}")
# 输出结果
# 原列表: [64, 34, 25, 12, 22, 11, 90]
# 升序排序: [11, 12, 22, 25, 34, 64, 90]
# 原列表未修改: [64, 34, 25, 12, 22, 11, 90]
# 降序排序: [90, 64, 34, 25, 22, 12, 11]
示例2:字符串排序
代码示例
# 字符串按字典序排序
words = ["banana", "apple", "cherry", "date"]
sorted_words = sorted(words)
print(f"字典序排序: {sorted_words}")
# 按长度排序
sorted_by_len = sorted(words, key=len)
print(f"按长度排序: {sorted_by_len}")
# 忽略大小写排序
mixed_case = ["Banana", "apple", "Cherry", "date"]
sorted_ignore_case = sorted(mixed_case, key=str.lower)
print(f"忽略大小写: {sorted_ignore_case}")
# 输出结果
# 字典序排序: ['apple', 'banana', 'cherry', 'date']
# 按长度排序: ['date', 'apple', 'banana', 'cherry']
# 忽略大小写: ['apple', 'Banana', 'Cherry', 'date']
四、sorted()高级排序技巧
示例1:字典列表排序
代码示例
# 学生数据
students = [
{"name": "张三", "score": 85, "age": 20},
{"name": "李四", "score": 92, "age": 19},
{"name": "王五", "score": 78, "age": 21},
{"name": "赵六", "score": 92, "age": 20},
]
# 按分数降序
by_score = sorted(students, key=lambda x: x["score"], reverse=True)
print("按分数降序:")
for s in by_score:
print(f" {s['name']}: {s['score']}分")
# 多条件排序:先按分数降序,再按年龄升序
by_score_age = sorted(students, key=lambda x: (-x["score"], x["age"]))
print("\n按分数降序,年龄升序:")
for s in by_score_age:
print(f" {s['name']}: {s['score']}分, {s['age']}岁")
# 输出结果
# 按分数降序:
# 李四: 92分
# 赵六: 92分
# 张三: 85分
# 王五: 78分
#
# 按分数降序,年龄升序:
# 李四: 92分, 19岁
# 赵六: 92分, 20岁
# 张三: 85分, 20岁
# 王五: 78分, 21岁
示例2:operator模块排序
代码示例
from operator import itemgetter, attrgetter
# 使用itemgetter排序(比lambda更快)
students = [
("张三", 85, 20),
("李四", 92, 19),
("王五", 78, 21),
]
# 按分数(索引1)排序
by_score = sorted(students, key=itemgetter(1), reverse=True)
print(f"按分数排序: {by_score}")
# 多条件排序
by_score_age = sorted(students, key=itemgetter(1, 2))
print(f"按分数和年龄排序: {by_score_age}")
# 输出结果
# 按分数排序: [('李四', 92, 19), ('张三', 85, 20), ('王五', 78, 21)]
# 按分数和年龄排序: [('王五', 78, 21), ('张三', 85, 20), ('李四', 92, 19)]
五、sum()求和函数
sum() 是Python内置的求和函数,用于计算可迭代对象中所有元素的总和。它支持数字类型(int、float、complex),并且可以通过start参数指定初始值。
示例1:基础求和
代码示例
# 整数求和
numbers = [1, 2, 3, 4, 5]
total = sum(numbers)
print(f"列表: {numbers}")
print(f"总和: {total}")
# 浮点数求和
floats = [1.5, 2.5, 3.0, 4.5]
float_total = sum(floats)
print(f"浮点数列表: {floats}")
print(f"浮点数总和: {float_total}")
# 元组求和
tup = (10, 20, 30)
tup_sum = sum(tup)
print(f"元组总和: {tup_sum}")
# 输出结果
# 列表: [1, 2, 3, 4, 5]
# 总和: 15
# 浮点数列表: [1.5, 2.5, 3.0, 4.5]
# 浮点数总和: 11.5
# 元组总和: 60
示例2:生成器表达式求和
代码示例
# 计算1到100的和
sum_100 = sum(range(1, 101))
print(f"1到100的和: {sum_100}")
# 计算平方和
sum_squares = sum(x**2 for x in range(1, 6))
print(f"1^2 + 2^2 + 3^2 + 4^2 + 5^2 = {sum_squares}")
# 条件求和:计算偶数和
sum_evens = sum(x for x in range(1, 11) if x % 2 == 0)
print(f"1到10中偶数的和: {sum_evens}")
# 输出结果
# 1到100的和: 5050
# 1^2 + 2^2 + 3^2 + 4^2 + 5^2 = 55
# 1到10中偶数的和: 30
六、sum()的start参数
sum(iterable, start) 的第二个参数 start 用于指定求和的初始值。最终结果等于 start + sum(iterable)。
示例1:基础start用法
代码示例
# 带初始值求和
numbers = [1, 2, 3, 4, 5]
result1 = sum(numbers, 10)
print(f"sum([1,2,3,4,5], 10) = {result1}")
result2 = sum(numbers, 100)
print(f"sum([1,2,3,4,5], 100) = {result2}")
# 输出结果
# sum([1,2,3,4,5], 10) = 25
# sum([1,2,3,4,5], 100) = 115
示例2:列表拼接(不推荐)
代码示例
# sum()可以用于列表拼接(但效率低)
lists = [[1, 2], [3, 4], [5, 6]]
# 使用sum()拼接
flattened = sum(lists, [])
print(f"拼接结果: {flattened}")
# 推荐方式:使用itertools.chain或列表推导式
from itertools import chain
flattened_chain = list(chain.from_iterable(lists))
print(f"chain拼接: {flattened_chain}")
# 输出结果
# 拼接结果: [1, 2, 3, 4, 5, 6]
# chain拼接: [1, 2, 3, 4, 5, 6]
注意:虽然
sum(lists, [])可以拼接列表,但时间复杂度为O(n^2),效率很低。对于大量列表拼接,推荐使用itertools.chain.from_iterable()或列表推导式[item for sublist in lists for item in sublist]。
七、三函数对比表格
八、注意事项
-
reversed()返回迭代器:reversed()返回的是迭代器对象,只能遍历一次。如果需要多次使用,需转换为列表:
list(reversed(data))。 -
sorted()稳定性:Python的sorted()使用Timsort算法,是稳定排序。相等元素的相对顺序在排序后保持不变。
-
sum()类型限制:sum()只能用于数值类型求和,不能用于字符串拼接。字符串拼接应使用
"".join()。 -
浮点数精度:对于大量浮点数求和,可能存在精度损失。需要高精度时可使用
math.fsum()。
小贴士
链式调用:这三个函数可以链式调用实现复杂操作。例如 sum(sorted(numbers, reverse=True)[:5]) 可以计算前5大数的和。list(reversed(sorted(data))) 等价于 sorted(data, reverse=True),但后者更高效。
常见问题
reversed()和list.reverse()有什么区别?
reversed()返回一个新的迭代器,不修改原列表,适用于任何可迭代对象。list.reverse()是列表的原地方法,直接修改原列表并返回None,只适用于列表。如果需要保留原数据,使用reversed();如果不需要原数据,使用reverse()更节省内存。
sorted()和list.sort()应该用哪个?
如果需要保留原列表,使用sorted();如果不需要原列表且对象是列表,使用list.sort()更节省内存。sorted()适用于任何可迭代对象,list.sort()只适用于列表。两者使用相同的Timsort算法,性能相当。
sum()的start参数有什么实际用途?
start参数常用于设置基准值或偏移量。例如计算总分时加上基础分:sum(scores, base_score)。也可以用于累积计算,如 sum(new_items, len(existing_items)) 计算总数。
如何提高浮点数求和的精度?
对于大量浮点数求和,使用 math.fsum() 代替sum()。fsum()使用扩展精度算法,能避免浮点数累加时的精度损失。例如:math.fsum([0.1] * 10) 返回精确的1.0。
十一、练习题
练习1
给定一个包含学生信息的列表,每个学生是字典 {"name": str, "scores": list}。编写函数 get_top_students(students, n=3),返回总分排名前n的学生名单。要求:(1) 使用sum()计算总分;(2) 使用sorted()排序;(3) 返回包含姓名和总分的新列表。编写完整代码并测试。
练习2
编写函数 palindrome_checker(text),检查文本是否为回文(忽略大小写和空格)。要求使用reversed()实现,不使用切片。编写完整代码并测试,包含 "A man a plan a canal Panama" 等测试用例。
本文涉及AI创作
内容由AI创作,请仔细甄别