脚本之家,脚本语言编程技术及教程分享平台!
分类导航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服务器之家 - 脚本之家 - Python - Python 的 sum() Pythonic 的求和方法详细

Python 的 sum() Pythonic 的求和方法详细

2022-01-25 00:19Yuchuan Python

Python 的内置函数sum()是一种对数值列表求和的有效且Pythonic 的方法。将多个数字相加是许多计算中常见的中间步骤,因此sum()对于 Python 程序员来说是一个非常方便的工具。下面文章就让我们一起来看具体内容吧

前言:

我们现在可以使用 Python 的内置函数sum()将多个数值相加。此函数提供了一种高效、可读且 Pythonic 的方法来解决代码中的求和问题。如果您正在处理需要对数值求和的数学计算,那么它sum()可以成为您的救星。

Python 的内置函数sum()是一种对数值列表求和的有效且Pythonic 的方法。将多个数字相加是许多计算中常见的中间步骤,因此sum()对于 Python 程序员来说是一个非常方便的工具。

作为一个额外的和有趣的使用情况,您可以连接列表和元组使用sum(),当你需要拼合列表的列表,可以很方便。

在本教程中,我们将学习如何:

  • 使用通用技术和工具手工对数值求和
  • 使用Pythonsum()高效地添加多个数值
  • 拼接列表和元组与sum()
  • 使用sum()接近普通求和问题
  • 使用适当的值的参数中sum()
  • 之间做出选择sum()和替代工具来总结和串连对象

这些知识将帮助您使用sum()或其他替代和专用工具有效地处理和解决代码中的求和问题。

1、理解求和问题

将数值相加是编程中一个相当普遍的问题。例如,假设您有一个数字列表 [1, 2, 3, 4, 5] 并且想要将它们加在一起以计算它们的总和。使用标准算术,您将执行以下操作:

1 + 2 + 3 + 4 + 5 = 15

就数学而言,这个表达式非常简单。它会引导您完成一系列简短的加法,直到您找到所有数字的总和。

可以手动进行这个特定的计算,但想象一下其他一些不太可能的情况。如果您有一个特别长的数字列表,手动添加可能效率低下且容易出错。如果您甚至不知道列表中有多少项会发生什么?最后,想象一个场景,您需要添加的项目数量动态或不可预测地发生变化。

在这种情况下,无论您的数字列表是长列表还是短列表,Python 在解决求和问题方面都非常有用。

如果您想通过从头开始创建自己的解决方案来对数字求和,那么您可以尝试使用for循环:

?
1
2
3
4
5
6
7
8
9
10
>>>
>>> numbers = [1, 2, 3, 4, 5]
>>> total = 0
 
>>> for number in numbers:
...     total += number
...
 
>>> total
15

在这里,您首先创建total并将其初始化为0. 此变量用作累加器,您可以在其中存储中间结果,直到获得最终结果。循环通过使用增广赋值累加每个连续值来迭代numbers和更新。total

您还可以将for循环包装在函数中。这样,我们可以为不同的列表重用代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
>>>
>>> def sum_numbers(numbers):
...     total = 0
...     for number in numbers:
...         total += number
...     return total
...
 
>>> sum_numbers([1, 2, 3, 4, 5])
15
 
>>> sum_numbers([])
0

在 中sum_numbers() ,您将一个可迭代对象——特别是一个数值列表——作为参数,并返回输入列表中值的总和。如果输入列表为空,则函数返回0。该for循环与您之前看到的相同。

您还可以使用递归代替迭代。递归是一种函数式编程技术,其中函数在其自己的定义中被调用。换句话说,递归函数在循环中调用自身:

?
1
2
3
4
5
6
7
8
9
>>>
>>> def sum_numbers(numbers):
...     if len(numbers) == 0:
...         return 0
...     return numbers[0] + sum_numbers(numbers[1:])
...
 
>>> sum_numbers([1, 2, 3, 4, 5])
15

当你定义一个递归函数时,你冒着陷入无限循环的风险。为了防止这种情况,您需要定义停止递归的基本情况和调用函数并启动隐式循环的递归情况。

在上面的例子中,基本情况意味着零长度列表的总和是0。递归情况意味着总和是第一个值numbers[0] ,加上其余值的总和numbers[1:] 。由于递归情况在每次迭代中使用较短的序列,因此您希望在numbers是零长度列表时遇到基本情况。作为最终结果,您将获得输入列表中所有项目的总和numbers

注意:在此示例中,如果您不检查空输入列表(您的基本情况),则sum_numbers()永远不会遇到无限递归循环。当您的numbers列表长度达到 时0,代码会尝试访问空列表中的项目,这会引发IndexError并中断循环。

使用这种实现,你永远不会从这个函数中得到一个总和。你IndexError每次都会得到一个。

Python 中对数字列表求和的另一种选择是使用reduce()from functools。要获取数字列表的总和,我们可以将任一operator.add或适当的lambda函数作为第一个参数传递给reduce():

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
>>>
>>> from functools import reduce
>>> from operator import add
 
>>> reduce(add, [1, 2, 3, 4, 5])
15
 
>>> reduce(add, [])
Traceback (most recent call last):
    ...
TypeError: reduce() of empty sequence with no initial value
 
>>> reduce(lambda x, y: x + y, [1, 2, 3, 4, 5])
15

您可以致电reduce()与减少或折叠,function与一起iterable作为参数。然后reduce()使用输入函数处理iterable并返回单个累积值。

在第一个示例中,归约函数是add(),它将两个数字相加。最终结果是 input 中数字的总和iterable。作为一个缺点,reduce()提出了一个TypeError当你与一个空的调用它iterable

在第二个示例中,约简函数是一个lambda返回两个数字相加的函数。

由于像这样的求和在编程中很常见,因此每次需要对一些数字求和时编写一个新函数是大量重复性工作。此外, usingreduce()不是您可用的最易读的解决方案。

Python 提供了专门的内置函数来解决这个问题。该函数被方便地调用sum() 。由于它是一个内置函数,因此您可以直接在代码中使用它,而无需导入任何内容。

2、Python 入门 sum()

可读性是Python 哲学背后最重要的原则之一。在对值列表求和时,可视化您要求循环执行的操作。您希望它遍历一些数字,将它们累加到一个中间变量中,然后返回最终和。但是,您可能可以想象一个不需要循环的更易读的求和版本。您希望 Python 取一些数字并将它们相加。

现在想想如何reduce()求和。使用reduce()可以说比基于循环的解决方案更不可读,更不直接。

这就是为什么将Python 2.3添加sum()为内置函数来为求和问题提供 Pythonic 解决方案的原因。Alex Martelli贡献了这个函数,它现在是对值列表求和的首选语法:

?
1
2
3
4
5
6
>>>
>>> sum([1, 2, 3, 4, 5])
15
 
>>> sum([])
0

哇!这很整洁,不是吗?它读起来像简单的英语,并清楚地传达您在输入列表上执行的操作。使用sum()for循环或reduce()调用更具可读性。与reduce() ,当您提供空的可迭代对象时sum()不会引发 a TypeError。相反,它可以理解地返回0.

我们可以sum()使用以下两个参数进行调用:

iterable是一个必需的参数,可以保存任何 Python 可迭代对象。可迭代对象通常包含数值,但也可以包含列表或元组。
start是一个可选参数,可以保存一个初始值。然后将该值添加到最终结果中。它默认为0.
在内部,从左到右sum()添加startplus 中的值iterable。输入iterable中的值通常是数字,但您也可以使用列表和元组。可选参数start可以接受数字、列表或元组,具体取决于传递给 的内容iterable。它不能带一个string

在以下两节中,您将了解sum()在代码中使用的基础知识。

2.1 必需的参数: iterable

接受任何 Python iterable 作为它的第一个参数使得sum()泛型、可重用和多态。由于此功能,您可以使用sum()列表、元组、集合range对象和字典

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
>>>
>>> # Use a list
>>> sum([1, 2, 3, 4, 5])
15
 
>>> # Use a tuple
>>> sum((1, 2, 3, 4, 5))
15
 
>>> # Use a set
>>> sum({1, 2, 3, 4, 5})
15
 
>>> # Use a range
>>> sum(range(1, 6))
15
 
>>> # Use a dictionary
>>> sum({1: "one", 2: "two", 3: "three"})
6
>>> sum({1: "one", 2: "two", 3: "three"}.keys())
6

在所有这些示例中,sum()计算输入迭代中所有值的算术和,而不管它们的类型。在两个字典示例中,都调用sum()返回输入字典键的总和。第一个示例默认对键求和,第二个示例由于.keys()调用输入字典而对键求和。

如果您的字典在其值中存储数字,并且您想对这些值而不是键进行求和,那么您可以.values()像.keys()示例中那样使用。

您还可以sum()将列表推导式用作参数。这是一个计算一系列值的平方和的示例:

?
1
2
3
>>>
>>> sum([x ** 2 for x in range(1, 6)])
55

Python 2.4向该语言添加了生成器表达式。同样,sum()当您使用生成器表达式作为参数时,按预期工作:

?
1
2
3
>>>
>>> sum(x ** 2 for x in range(1, 6))
55

这个例子展示了解决求和问题的最 Pythonic 技术之一。它在一行代码中提供了一个优雅、可读且高效的解决方案。

2.2 可选参数: start

第二个可选参数start允许您提供一个值来初始化求和过程。当您需要按顺序处理累积值时,此参数很方便:

?
1
2
3
4
5
6
>>>
>>> sum([1, 2, 3, 4, 5], 100# Positional argument
115
 
>>> sum([1, 2, 3, 4, 5], start=100# Keyword argument
115

在这里,您提供初始值100to start。净效果是sum()将此值添加到输入可迭代中的值的累积总和中。请注意,您可以start作为位置参数或关键字参数提供。后一个选项更加明确和可读。

如果您没有为 提供值start,则默认为0。默认值0确保返回输入值总和的预期行为。

3、对数值求和

的主要目的sum()是提供一种 Pythonic 方式来将数值相加。到目前为止,您已经了解了如何使用该函数对整数求和。此外,可以使用sum()任何其他数字Python类型,比如floatcomplexdecimal.Decimal,和fractions.Fraction

以下是使用sum()不同数字类型的值的几个示例:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
>>>
>>> from decimal import Decimal
>>> from fractions import Fraction
 
>>> # Sum floating-point numbers
>>> sum([10.2, 12.5, 11.8])
34.5
>>> sum([10.2, 12.5, 11.8, float("inf")])
inf
>>> sum([10.2, 12.5, 11.8, float("nan")])
nan
 
>>> # Sum complex numbers
>>> sum([3 + 2j, 5 + 6j])
(8+8j)
 
>>> # Sum Decimal numbers
>>> sum([Decimal("10.2"), Decimal("12.5"), Decimal("11.8")])
Decimal('34.5')
 
>>> # Sum Fraction numbers
>>> sum([Fraction(51, 5), Fraction(25, 2), Fraction(59, 5)])
Fraction(69, 2)

在这里,您第一次使用sum()与浮点数字。值得注意的是,当您使用特殊符号infnan在调用float("inf")和 中时函数的行为float("nan") 。第一个符号代表一个无限值,因此sum()返回inf。第二个符号代表NaN(不是数字)值。由于您无法将数字与非数字相加,因此您会得到nan结果。

其他的例子总和iterablescomplexDecimalFraction数字。在所有情况下,sum()使用适当的数字类型返回结果累积总和。

4、连接序列

尽管sum()主要用于对数值进行操作,但您也可以使用该函数来连接列表和元组等序列。为此,您需要为 提供适当的值start:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
>>>
>>> num_lists = [[1, 2, 3], [4, 5, 6]]
>>> sum(num_lists, start=[])
[1, 2, 3, 4, 5, 6]
 
>>> # Equivalent concatenation
>>> [1, 2, 3] + [4, 5, 6]
[1, 2, 3, 4, 5, 6]
 
>>> num_tuples = ((1, 2, 3), (4, 5, 6))
>>> sum(num_tuples, start=())
(1, 2, 3, 4, 5, 6)
 
>>> # Equivalent concatenation
>>> (1, 2, 3) + (4, 5, 6)
(1, 2, 3, 4, 5, 6)

在这些示例中,您使用sum()连接列表和元组。这是一个有趣的功能,您可以使用它来展平列表列表或元组元组。这些示例工作的关键要求是为 选择适当的值start。例如,如果要连接列表,则start需要持有一个列表。

在上面的示例中,sum()在内部执行连接操作,因此它仅适用于支持连接的序列类型,字符串除外:

?
1
2
3
4
5
6
>>>
>>> num_strs = ["123", "456"]
>>> sum(num_strs, "0")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: sum() can't sum strings [use ''.join(seq) instead]

当您尝试使用sum()来连接字符串时,您会得到一个TypeError. 正如异常消息所暗示的那样,您应该使用str.join()来连接 Python 中的字符串。稍后,当您进入使用替代sum()方法部分时,您将看到使用此方法的示例。

5、使用 Python 进行练习 sum()

到目前为止,您已经学习了使用sum(). 您已经学习了如何使用此函数将数值相加,以及如何连接列表和元组等序列。

在本节中,您将查看更多有关何时以及如何sum()在代码中使用的示例。通过这些实际示例,您将了解到当您执行需要查找一系列数字之和作为中间步骤的计算时,此内置函数非常方便。

您还将了解到这sum()在您使用列表和元组时会很有帮助。您将看到的一个特殊示例是当您需要展平列表列表时。

5.1 计算累积和

您将编写的第一个示例与如何利用start参数对数值的累积列表求和有关。

假设您正在开发一个系统来管理给定产品在多个不同销售点的销售。每天,您都会收到来自每个销售点的销售单位报告。您需要系统地计算累计总和,以了解整个公司在一周内销售了多少件商品。要解决此问题,您可以使用sum()

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
>>>
>>> cumulative_sales = 0
 
>>> monday = [50, 27, 42]
>>> cumulative_sales = sum(monday, start=cumulative_sales)
>>> cumulative_sales
119
 
>>> tuesday = [12, 32, 15]
>>> cumulative_sales = sum(tuesday, start=cumulative_sales)
>>> cumulative_sales
178
 
>>> wednesday = [20, 24, 42]
>>> cumulative_sales = sum(wednesday, start=cumulative_sales)
>>> cumulative_sales
264
    ...

通过使用start,您可以设置一个初始值来初始化总和,这允许您将连续单位添加到先前计算的小计中。在本周末,您将获得公司的销售单位总数。

5.2 计算样本的平均值

的另一个实际用例sum()是在进行进一步计算之前将其用作中间计算。例如,假设您需要计算数值样本的算术平均值。算术平均值,也称为平均值,是样本中值的总和除以值或数据点的数量。

如果你有样本 [2, 3, 4, 2, 3, 6, 4, 2] 并且你想手工计算算术平均值,那么你可以解决这个操作:

(2 + 3 + 4 + 2 + 3 + 6 + 4 + 2) / 8 = 3.25

如果您想通过使用 Python 加快速度,您可以将其分为两部分。此计算的第一部分,即您将数字相加,是 的任务sum() 。运算的下一部分,即除以 8,使用样本中的数字计数。要计算您的除数,您可以使用len()

?
1
2
3
4
5
>>>
>>> data_points = [2, 3, 4, 2, 3, 6, 4, 2]
 
>>> sum(data_points) / len(data_points)
3.25

在这里,调用sum()计算样本中数据点的总和。接下来,您使用len()来获取数据点的数量。最后,您执行所需的除法以计算样本的算术平均值。

在实践中,您可能希望将此代码转换为具有一些附加功能的函数,例如描述性名称和检查空样本:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
>>>
>>> # Python >= 3.8
 
>>> def average(data_points):
...     if (num_points := len(data_points)) == 0:
...         raise ValueError("average requires at least one data point")
...     return sum(data_points) / num_points
...
 
>>> average([2, 3, 4, 2, 3, 6, 4, 2])
3.25
 
>>> average([])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in average
ValueError: average requires at least one data point

在内部average() ,您首先检查输入样本是否有任何数据点。如果没有,那么你ValueError用一个描述性的消息来引发。在此示例中,您使用walrus 运算符将数据点的数量存储在变量中,num_points以便您无需len()再次调用。该return语句计算样本的算术平均值,并将其发送回调用代码。

注意:计算数据样本的平均值是统计和数据分析中的常见操作。Python 标准库提供了一个方便的模块,称为statistics处理这些类型的计算。

statistics模块中,您将找到一个名为 的函数mean()

?
1
2
3
4
5
6
7
8
9
10
>>>
>>> from statistics import mean
 
>>> mean([2, 3, 4, 2, 3, 6, 4, 2])
3.25
 
>>> mean([])
Traceback (most recent call last):
    ...
statistics.StatisticsError: mean requires at least one data point

statistics.mean()函数的行为与average()您之前编码的函数非常相似。当您mean()使用数值样本进行调用时,您将获得输入数据的算术平均值。当您将空列表传递给 时mean() ,您将获得一个statistics.StatisticsError.

请注意,当您average()使用适当的样本调用时,您将获得所需的平均值。如果您average()使用空样本调用,那么您会得到ValueError预期的结果。

5.3 求两个序列的点积

您可以使用的另一个问题sum()是找到两个等长数值序列的点积。点积的代数和的产品在输入序列的每对值中的。例如,如果您有序列 (1, 2, 3) 和 (4, 5, 6),那么您可以使用加法和乘法手动计算它们的点积:

1 × 4 + 2 × 5 + 3 × 6 = 32

要从输入序列中提取连续的值对,您可以使用zip(). 然后您可以使用生成器表达式将每对值相乘。最后,sum()可以总结产品:

?
1
2
3
4
5
6
>>>
>>> x_vector = (1, 2, 3)
>>> y_vector = (4, 5, 6)
 
>>> sum(x * y for x, y in zip(x_vector, y_vector))
32

使用zip() ,您可以使用来自每个输入序列的值生成一个元组列表。生成器表达式循环遍历每个元组,同时将先前排列的连续值对乘以zip() 。最后一步是使用 将产品添加在一起sum()

上面示例中的代码有效。然而,点积是为等长的序列定义的,所以如果你提供不同长度的序列会发生什么?在这种情况下,zip()忽略最长序列中的额外值,这会导致不正确的结果。

为了处理这种可能性,我们可以将调用包装sum()在自定义函数中,并为输入序列的长度提供适当的检查:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
>>>
>>> def dot_product(x_vector, y_vector):
...     if len(x_vector) != len(y_vector):
...         raise ValueError("Vectors must have equal sizes")
...     return sum(x * y for x, y in zip(x_vector, y_vector))
...
 
>>> dot_product((1, 2, 3), (4, 5, 6))
32
 
>>> dot_product((1, 2, 3, 4), (5, 6, 3))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in dot_product
ValueError: Vectors must have equal sizes

这里,dot_product()将两个序列作为参数并返回它们对应的点积。如果输入序列的长度不同,则该函数会引发 a ValueError

在自定义函数中嵌入功能允许您重用代码。它还使您有机会对函数进行描述性命名,以便用户仅通过阅读函数名称就知道该函数的作用。

5.4 展平列表列表

展平列表列表是 Python 中的一项常见任务。假设您有一个列表列表,需要将其展平为一个包含原始嵌套列表中所有项目的列表。您可以使用多种方法中的任何一种在 Python 中展平列表。例如,您可以使用for循环,如以下代码所示:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
>>>
>>> def flatten_list(a_list):
...     flat = []
...     for sublist in a_list:
...         flat += sublist
...     return flat
...
 
>>> matrix = [
...     [1, 2, 3],
...     [4, 5, 6],
...     [7, 8, 9],
... ]
 
>>> flatten_list(matrix)
[1, 2, 3, 4, 5, 6, 7, 8, 9]

在 中flatten_list() ,循环遍历 中包含的所有嵌套列表a_list。然后它flat使用增强赋值操作 ( +=)将它们连接起来。结果,您会得到一个平面列表,其中包含原始嵌套列表中的所有项目。

但是坚持住!您已经sum()在本教程中学习了如何使用来连接序列。您可以使用该功能来像上面的示例中那样展平列表列表吗?是的!就是这样:

?
1
2
3
4
5
6
7
8
9
>>>
>>> matrix = [
...     [1, 2, 3],
...     [4, 5, 6],
...     [7, 8, 9],
... ]
 
>>> sum(matrix, [])
[1, 2, 3, 4, 5, 6, 7, 8, 9]

那很快!一行代码,matrix现在是一个平面列表。但是,使用sum()似乎不是最快的解决方案。

任何暗示串联的解决方案的一个重要缺点是,在幕后,每个中间步骤都会创建一个新列表。这在内存使用方面可能非常浪费。最终返回的列表只是在每一轮连接中创建的所有列表中最近创建的列表。使用列表推导式可确保您只创建和返回一个列表:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
>>>
>>> def flatten_list(a_list):
...     return [item for sublist in a_list for item in sublist]
...
 
>>> matrix = [
...     [1, 2, 3],
...     [4, 5, 6],
...     [7, 8, 9],
... ]
 
>>> flatten_list(matrix)
[1, 2, 3, 4, 5, 6, 7, 8, 9]

这个新版本flatten_list()在内存使用方面效率更高,浪费更少。然而,嵌套的理解可能难以阅读和理解。

使用.append()可能是扁平化列表列表最易读和 Pythonic 的方式:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
>>>
>>> def flatten_list(a_list):
...     flat = []
...     for sublist in a_list:
...         for item in sublist:
...             flat.append(item)
...     return flat
...
 
>>> matrix = [
...     [1, 2, 3],
...     [4, 5, 6],
...     [7, 8, 9],
... ]
 
>>> flatten_list(matrix)
[1, 2, 3, 4, 5, 6, 7, 8, 9]

在这个版本中flatten_list() ,一个人阅读你的代码可以看出,功能遍历每个sublista_list。在第一个for循环中,它遍历每个iteminsublist以最终flat使用.append(). 就像前面的推导一样,这个解决方案在这个过程中只创建了一个列表。这种解决方案的一个优点是它的可读性很强。

6、使用替代品 sum()

正如您已经了解到的,sum()一般来说,对于处理数值很有帮助。但是,在处理浮点数时,Python 提供了一种替代工具。在 中math,您会找到一个名为的函数fsum() ,它可以帮助您提高浮点计算的总体精度。

您可能有一项任务,您希望连接或链接多个可迭代对象,以便您可以将它们作为一个整体处理。对于这种情况,您可以查看itertools模块的 function chain()

您可能还有一个要连接字符串列表的任务。您在本教程中了解到,无法sum()用于连接字符串。这个函数不是为字符串连接而构建的。最 Pythonic 的替代方法是使用str.join().

6.1 对浮点数求和: math.fsum()

如果您的代码不断使用 对浮点数求和sum() ,那么您应该考虑math.fsum()改用 。此函数比 更仔细地执行浮点计算sum(),从而提高计算精度。

根据其文档,fsum()“通过跟踪多个中间部分和来避免精度损失。” 该文档提供了以下示例:

?
1
2
3
4
5
6
7
8
>>>
>>> from math import fsum
 
>>> sum([.1, .1, .1, .1, .1, .1, .1, .1, .1, .1])
0.9999999999999999
 
>>> fsum([.1, .1, .1, .1, .1, .1, .1, .1, .1, .1])
1.0

使用fsum() ,您可以获得更精确的结果。但是,您应该注意这fsum()并不能解决浮点运算中的表示错误。以下示例揭示了此限制:

?
1
2
3
4
5
6
7
8
>>>
>>> from math import fsum
 
>>> sum([0.1, 0.2])
0.30000000000000004
 
>>> fsum([0.1, 0.2])
0.30000000000000004

在这些示例中,两个函数返回相同的结果。这是因为不可能准确地表示这两个值0.1和0.2二进制浮点数:

?
1
2
3
4
5
6
>>>
>>> f"{0.1:.28f}"
'0.1000000000000000055511151231'
 
>>> f"{0.2:.28f}"
'0.2000000000000000111022302463'

sum()但是,与 不同的是,fsum()当您将非常大和非常小的数字相加时,可以帮助您减少浮点错误传播:

?
1
2
3
4
5
6
7
8
9
10
11
12
>>>
>>> from math import fsum
 
>>> sum([1e-16, 1, 1e16])
1e+16
>>> fsum([1e-16, 1, 1e16])
1.0000000000000002e+16
 
>>> sum([1, 1, 1e100, -1e100] * 10_000)
0.0
>>> fsum([1, 1, 1e100, -1e100] * 10_000)
20000.0

哇!第二个例子非常令人惊讶并且完全失败sum() 。使用sum(),您将得到0.0结果。这与 的正确结果相去甚远20000.0,正如您所得到的fsum()

6.2 连接可迭代对象 itertools.chain()

如果您正在寻找一个方便的工具来连接或链接一系列可迭代对象,请考虑使用chain()from itertools。此函数可以采用多个迭代器并构建一个迭代器,该迭代器从第一个、第二个中产生项目,依此类推,直到耗尽所有输入迭代:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
>>>
>>> from itertools import chain
 
>>> numbers = chain([1, 2, 3], [4, 5, 6], [7, 8, 9])
>>> numbers
<itertools.chain object at 0x7f0d0f160a30>
>>> next(numbers)
1
>>> next(numbers)
2
 
>>> list(chain([1, 2, 3], [4, 5, 6], [7, 8, 9]))
[1, 2, 3, 4, 5, 6, 7, 8, 9]

当您调用 时chain(),您会从输入可迭代对象中获得项目的迭代器。在本例中,您可以numbers使用访问连续的项目next()。如果你想使用一个列表,那么你可以使用它list()来使用迭代器并返回一个常规的 Python 列表。

chain() Python 中展平列表列表也是一个不错的选择:

?
1
2
3
4
5
6
7
>>>
>>> from itertools import chain
 
>>> matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
 
>>> list(chain(*matrix))
[1, 2, 3, 4, 5, 6, 7, 8, 9]

要使用 扁平化列表列表chain() ,您需要使用可迭代解包运算符( *)。此运算符解包所有输入可迭代对象,以便chain()可以使用它们并生成相应的迭代器。最后一步是调用list()以构建所需的平面列表。

6.3 连接字符串 str.join()

正如您已经看到的,sum()不连接或连接字符串。如果您需要这样做,那么 Python 中可用的首选和最快的工具是str.join(). 此方法将一系列字符串作为参数并返回一个新的连接字符串:

?
1
2
3
4
5
>>>
>>> greeting = ["Hello,", "welcome to", "Real Python!"]
 
>>> " ".join(greeting)
'Hello, welcome to Real Python!'

使用.join()是连接字符串的最有效和 Pythonic 的方式。在这里,您使用字符串列表作为参数并从输入构建单个字符串。请注意,.join()在连接期间使用您调用方法的字符串作为分隔符。在此示例中,您调用.join()由单个空格字符 ( " ")组成的字符串,因此原始字符串 fromgreeting在最终字符串中由空格分隔。

7、结论

您现在可以使用 Python 的内置函数sum()将多个数值相加。此函数提供了一种高效、可读且 Pythonic 的方法来解决代码中的求和问题。如果您正在处理需要对数值求和的数学计算,那么它sum()可以成为您的救星。

到此这篇关于Python 的 sum() Pythonic 的求和方法详细的文章就介绍到这了,更多相关Python 的 sum() Pythonic 的求和方法内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://juejin.cn/post/7018807788658753544

延伸 · 阅读

精彩推荐