Python's sum(): Способ суммирования значений на языке Python

Оглавление

Смотрите сейчас, к этому уроку прилагается соответствующий видеокурс, созданный командой Real Python. Посмотрите его вместе с письменным руководством, чтобы углубить свое понимание: Суммирование значений по-питонски с помощью sum()

Встроенная функция Python sum() - это эффективный и понятный на языке Python способ суммирования списка числовых значений. Сложение нескольких чисел вместе является обычным промежуточным этапом во многих вычислениях, поэтому sum() является довольно удобным инструментом для программиста на Python.

В качестве дополнительного и интересного варианта использования вы можете объединить списки и кортежи с помощью sum(), что может быть удобно, когда вам нужно сгладить список списков.

В этом руководстве вы узнаете, как:

  • Суммируйте числовые значения вручную, используя общие приемы и инструменты
  • Используйте Python'ы sum() для эффективного добавления нескольких числовых значений
  • Объединяйте списки и кортежи с помощью sum()
  • Используйте sum() для решения общих задач суммирования
  • Используйте соответствующие значения для аргументов в sum()
  • Выберите между sum() и альтернативными инструментами для суммирования и объединения объектов

Эти знания помогут вам эффективно подходить к решению задач суммирования в вашем коде с помощью sum() или других альтернативных и специализированных инструментов.

Бесплатный бонус: Нажмите здесь, чтобы получить шпаргалку по Python и изучить основы Python 3, такие как работа с типами данных, словари, списки и функции Python.

Понимание проблемы суммирования

Суммирование числовых значений - довольно распространенная проблема в программировании. Например, предположим, что у вас есть список чисел [1, 2, 3, 4, 5] и вы хотите сложить их вместе, чтобы вычислить их общую сумму. Используя стандартную арифметику, вы сделаете что-то вроде этого:

1 + 2 + 3 + 4 + 5 = 15

Что касается математики, то это выражение довольно простое. Оно поможет вам выполнить небольшую серию сложений, пока вы не найдете сумму всех чисел.

Это конкретное вычисление можно выполнить вручную, но представьте себе некоторые другие ситуации, в которых это может оказаться невозможным. Если у вас особенно длинный список чисел, добавление вручную может быть неэффективным и чреватым ошибками. Что произойдет, если вы даже не знаете, сколько элементов в списке? Наконец, представьте ситуацию, в которой количество элементов, которые вам нужно добавить, меняется динамически или непредсказуемо.

В подобных ситуациях, независимо от того, есть ли у вас длинный или короткий список чисел, Python может быть весьма полезен для решения задач суммирования.

Если вы хотите, чтобы сумма чисел на создание собственного решения с нуля, то можно попробовать использовать for петли:

>>> numbers = [1, 2, 3, 4, 5]
>>> total = 0

>>> for number in numbers:
...     total += number
...

>>> total
15


Здесь вы сначала создаете total и инициализируете его как 0. Эта переменная работает как накопитель, в котором вы сохраняете промежуточные результаты, пока не получите окончательный результат. Цикл выполняет итерацию по numbers и обновляет total, накапливая каждое последующее значение с помощью расширенного присваивания .

Вы также можете обернуть цикл for в функцию . Таким образом, вы можете повторно использовать код для разных списков:

>>> 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 такой же, как вы видели ранее.

Вы также можете использовать рекурсию вместо итерации. Рекурсия - это метод функционального программирования, при котором функция вызывается в пределах ее собственного определения. Другими словами, рекурсивная функция вызывает саму себя в цикле:

>>> 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() из functools. Чтобы получить сумму из списка чисел, вы можете передать либо operator.add, либо соответствующую функцию lambda в качестве первого аргумента в reduce():

>>> 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(), которая принимает два числа и складывает их вместе. Конечным результатом является сумма чисел во входных данных iterable. В качестве недостатка, reduce() вызывает TypeError когда вы вызываете его с пустым iterable.

Во втором примере функция сокращения представляет собой функцию lambda, которая возвращает результат сложения двух чисел.

Поскольку подобные суммирования являются обычным делом в программировании, написание новой функции каждый раз, когда вам нужно просуммировать некоторые числа, требует много повторяющейся работы. Кроме того, использование reduce() - не самое удобное решение из доступных вам.

Python предоставляет специальную встроенную функцию для решения этой проблемы. Функция удобно называется sum(). Поскольку это встроенная функция, вы можете использовать ее непосредственно в своем коде, не импортируя что-либо.

Начало работы с Python sum()

Читаемость - один из важнейших принципов, лежащих в основе философии Python. Визуализируйте, что вы просите цикл выполнить при суммировании списка значений. Вы хотите, чтобы он перебирал некоторые числа, накапливал их в промежуточной переменной и возвращал конечную сумму. Однако вы, вероятно, можете представить себе более удобочитаемую версию суммирования, которая не нуждается в цикле. Вы хотите, чтобы Python брал некоторые числа и суммировал их вместе.

Теперь подумайте о том, как reduce() выполняет суммирование. Использование reduce(), возможно, менее читабельно и не так просто, чем даже решение на основе циклов.

Вот почему В Python 2.3 добавлена sum() в качестве встроенной функции для предоставления питонического решения задачи суммирования. Алекс Мартелли добавлена функция, которая в настоящее время является предпочтительным синтаксисом для суммирования списка значений:

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

>>> sum([])
0


Ничего себе! Это здорово, не так ли? Читается как обычный английский и четко описывает действие, которое вы выполняете в списке ввода. Использование sum() намного удобнее для чтения, чем цикл for или вызов reduce(). В отличие от reduce(), sum() не вызывает TypeError, когда вы предоставляете пустую итерируемую строку. Вместо этого, по понятным причинам, возвращается 0.

Вы можете вызвать sum() со следующими двумя аргументами:

  1. iterable это обязательный аргумент, который может содержать любую итерацию Python. Iterable обычно содержит числовые значения, но также может содержать списков или кортежей.
  2. start является необязательным аргументом, который может содержать начальное значение. Это значение затем добавляется к конечному результату. По умолчанию используется значение 0.

Внутри sum() добавляет start плюс значения в iterable слева направо. Значения во входных данных iterable обычно являются числами, но вы также можете использовать списки и кортежи. Необязательный аргумент start может принимать число, список или кортеж, в зависимости от того, что передается в iterable. Он не может принимать строку .

В следующих двух разделах вы познакомитесь с основами использования sum() в вашем коде.

Требуемый аргумент: iterable

Принятие любого iterable Python в качестве первого аргумента делает sum() универсальным, пригодным для повторного использования и полиморфным. Благодаря этой функции вы можете использовать sum() со списками, кортежами, наборами, range объектов и словарями:

>>> # 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() с пониманием списка в качестве аргумента. Вот пример, который вычисляет сумму квадратов диапазона значений:

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


В Python 2.4 добавлены генераторные выражения в язык. Опять же, sum() работает так, как ожидалось, когда вы используете генераторное выражение в качестве аргумента:

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


В этом примере показан один из наиболее распространенных методов решения задачи суммирования на языке Python. Он предоставляет элегантное, удобочитаемое и эффективное решение в одной строке кода.

Необязательный аргумент: start

Второй необязательный аргумент, start, позволяет указать значение для инициализации процесса суммирования. Этот аргумент удобен, когда вам нужно последовательно обрабатывать суммарные значения:

>>> sum([1, 2, 3, 4, 5], 100)  # Positional argument
115

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


Здесь вы вводите начальное значение от 100 до start. Конечным результатом является то, что sum() добавляет это значение к совокупной сумме значений во входной итерационной таблице. Обратите внимание, что вы можете указать start в качестве позиционного аргумента или в качестве ключевого аргумента. Последний вариант гораздо более понятен и удобочитаем.

Если вы не указываете значение start, то по умолчанию используется значение 0. Значение по умолчанию 0 обеспечивает ожидаемый результат возврата общей суммы входных значений.

Суммирование числовых значений

Основная цель sum() - предоставить питонический способ сложения числовых значений. До этого момента вы видели, как использовать функцию для суммирования целых чисел. Кроме того, вы можете использовать sum() с любыми другими числовыми типами Python, такими как float, complex, decimal.Decimal, и fractions.Fraction.

Вот несколько примеров использования sum() со значениями разных числовых типов:

>>> 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() с числами с плавающей запятой. Стоит отметить поведение функции при использовании специальных символов inf и nan в вызовах float("inf") и float("nan"). Первый символ представляет собой бесконечное значение , поэтому sum() возвращает inf. Второй символ представляет NaN (не число)> значений. Поскольку вы не можете добавлять числа к другим значениям, вы получите nan в результате.

В других примерах суммируются повторяющиеся значения чисел complex, Decimal, и Fraction. Во всех случаях sum() возвращает итоговую совокупную сумму, используя соответствующий числовой тип.

Объединяющие последовательности

Несмотря на то, что sum() в основном предназначен для работы с числовыми значениями, вы также можете использовать эту функцию для объединения последовательностей, таких как списки и кортежи. Чтобы сделать это, вам необходимо указать соответствующее значение для start:

>>> 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() выполняет внутреннюю операцию объединения, поэтому она работает только с теми типами последовательностей, которые поддерживают объединение, за исключением строк:

>>> 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().

Практикуюсь с Python'ом sum()

На данный момент вы освоили основы работы с sum(). Вы узнали, как использовать эту функцию для сложения числовых значений, а также для объединения последовательностей, таких как списки и кортежи.

В этом разделе вы рассмотрите еще несколько примеров того, когда и как использовать sum() в вашем коде. Из этих практических примеров вы узнаете, что эта встроенная функция весьма удобна при выполнении вычислений, требующих нахождения суммы ряда чисел в качестве промежуточного шага.

Вы также узнаете, что sum() может быть полезно при работе со списками и кортежами. Особый пример, который вы рассмотрите, - это когда вам нужно сгладить список списков.

Вычисление совокупных сумм

Первый пример, который вы закодируете, связан с использованием аргумента start для суммирования совокупных списков числовых значений.

Допустим, вы разрабатываете систему для управления продажами определенного товара в нескольких различных точках продаж. Каждый день вы получаете отчет о проданных единицах из каждой точки продаж. Вам необходимо систематически подсчитывать совокупную сумму, чтобы знать, сколько единиц продукции было продано всей компанией за неделю. Для решения этой проблемы вы можете использовать sum():

>>> 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, вы задаете начальное значение для инициализации суммы, что позволяет добавлять последующие единицы к ранее рассчитанному промежуточному итогу. В конце недели вы получите общее количество проданных единиц компании.

Вычисление среднего значения выборки

Другим практическим вариантом использования sum() является использование его в качестве промежуточного вычисления перед выполнением дальнейших вычислений. Например, предположим, что вам нужно вычислить среднее арифметическое для выборки числовых значений. Среднее арифметическое, также известное как среднее значение, представляет собой общую сумму значений, деленную на количество значений, или точек данных, в выборке.

Если у вас есть образец [2, 3, 4, 2, 3, 6, 4, 2] и вы хотите вычислить среднее арифметическое вручную, то вы можете выполнить эту операцию:

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

Если вы хотите ускорить процесс с помощью Python, вы можете разбить его на две части. Первая часть этого вычисления, в которой вы складываете числа, - это задача для sum(). В следующей части операции, где вы делите на 8, используется количество чисел в вашем образце. Чтобы вычислить свой делитель, вы можете использовать len():

>>> data_points = [2, 3, 4, 2, 3, 6, 4, 2]

>>> sum(data_points) / len(data_points)
3.25


Здесь вызов sum() вычисляет общую сумму точек данных в вашей выборке. Далее вы используете len(), чтобы получить количество точек данных. Наконец, вы выполняете необходимое деление, чтобы вычислить среднее арифметическое значение выборки.

На практике вы можете захотеть превратить этот код в функцию с некоторыми дополнительными функциями, такими как описательное имя и проверка на наличие пустых образцов:

>>> # 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():

>>> 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, как и ожидалось.

Нахождение скалярного произведения двух последовательностей

Еще одна задача, которую вы можете решить с помощью sum(), - это найти скалярное произведение двух последовательностей числовых значений одинаковой длины. Точечное произведение - это алгебраическая сумма произведений каждой пары значений во входных последовательностях. Например, если у вас есть последовательности (1, 2, 3) и (4, 5, 6), то вы можете вычислить их скалярное произведение вручную, используя сложение и умножение:

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

Чтобы извлечь последовательные пары значений из входных последовательностей, вы можете использовать zip(). Затем вы можете использовать генераторное выражение для умножения каждой пары значений. Наконец, sum() можно суммировать результаты:

>>> 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() в пользовательскую функцию и обеспечить надлежащую проверку длины входных последовательностей:

>>> 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() принимает две последовательности в качестве аргументов и возвращает их соответствующее скалярное произведение. Если входные последовательности имеют разную длину, то функция генерирует ValueError.

Внедрение функциональности в пользовательскую функцию позволяет повторно использовать код. Это также дает возможность дать функции описательное название, чтобы пользователь знал, что делает функция, просто прочитав ее название.

Сглаживание списка списков

Сглаживание списка списков - обычная задача в Python. Допустим, у вас есть список списков и вам нужно сгладить его в единый список, содержащий все элементы из исходных вложенных списков. У вас есть варианты, когда вы решаете, как сглаживать списки в Python. Например, вы можете использовать цикл for, как в следующем коде:

>>> 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() для объединения последовательностей. Можете ли вы использовать эту функцию для выравнивания списка списков, как в примере выше? Да! Вот как это делается:

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

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


Это было быстро! Всего одна строка кода, и matrix теперь представляет собой плоский список. Однако использование sum() не кажется самым быстрым решением.

Использование понимания списка - еще один распространенный способ сгладить список list в Python:

>>> 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() используется алгоритм понимания вместо обычного цикла for. Однако вложенных пояснений может быть сложно читать и понимать.

Использование .append() - это еще один способ сгладить список списков:

>>> 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() тот, кто читает ваш код, может увидеть, что функция выполняет итерацию по каждому sublist в a_list. Во втором цикле for функция выполняет итерацию по каждому item в sublist, чтобы, наконец, заполнить новый список flat с помощью .append(). Можно утверждать, что удобочитаемость может быть преимуществом этого решения.

Использование альтернатив sum()

Как вы уже поняли, sum() полезен для работы с числовыми значениями в целом. Однако, когда дело доходит до работы с числами с плавающей запятой, Python предоставляет альтернативный инструмент. В math, Вы найдете функцию fsum() это может помочь вам улучшить общую точность вычисления с плавающей точкой.

Возможно, у вас есть задача, в которой вы хотите объединить или связать цепочкой несколько повторяющихся объектов, чтобы вы могли работать с ними как с одним целым. Для этого сценария вы можете обратиться к функции модуля itertools chain().

У вас также может возникнуть задача, в которой вы хотите объединить список строк. Из этого руководства вы узнали, что нет способа использовать sum() для объединения строк. Эта функция просто не была создана для объединения строк. Наиболее подходящей альтернативой на языке Python является использование str.join().

Суммирование чисел с плавающей запятой: math.fsum()

Если ваш код постоянно суммирует числа с плавающей запятой с помощью sum(), то вам следует рассмотреть возможность использования math.fsum() вместо этого. Эта функция выполняет вычисления с плавающей запятой более тщательно, чем sum(), что повышает точность ваших вычислений.

В соответствии с документацией , fsum() “ позволяет избежать потери точности путем отслеживания нескольких промежуточных частичных сумм.” В документации приведен следующий пример:

>>> 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() не устраняет ошибку представления в арифметике с плавающей запятой. Следующий пример раскрывает это ограничение:

>>> from math import fsum

>>> sum([0.1, 0.2])
0.30000000000000004

>>> fsum([0.1, 0.2])
0.30000000000000004


В этих примерах обе функции возвращают один и тот же результат. Это связано с невозможностью точного представления обоих значений 0.1 и 0.2 в двоичном формате с плавающей запятой:

>>> f"{0.1:.28f}"
'0.1000000000000000055511151231'

>>> f"{0.2:.28f}"
'0.2000000000000000111022302463'


Однако 

В отличие от sum(), fsum() может помочь вам уменьшить распространение ошибок с плавающей запятой при сложении очень больших и очень маленьких чисел вместе:

>>> 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().

Объединение повторяющихся переменных с itertools.chain()

Если вы ищете удобный инструмент для объединения в цепочку ряда повторяющихся переменных, то рассмотрите возможность использования chain() из itertools. Эта функция может принимать несколько итераций и создавать итератор, который выдает элементы из первой, из второй и так далее, пока не исчерпает все входные итерации:

>>> 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:

>>> 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() для создания желаемого плоского списка.

Объединение строк с помощью str.join()

Как вы уже видели, sum() не объединяет строки . Если вам нужно это сделать, то предпочтительным и самым быстрым инструментом, доступным в Python, является str.join(). Этот метод принимает последовательность строк в качестве аргумента и возвращает новую, объединенную строку:

>>> greeting = ["Hello,", "welcome to", "Real Python!"]

>>> " ".join(greeting)
'Hello, welcome to Real Python!'


Использование .join() является наиболее эффективным и основанным на Python способом объединения строк. Здесь вы используете список строк в качестве аргумента и создаете единую строку из входных данных. Обратите внимание, что .join() использует строку, для которой вы вызываете метод, в качестве разделителя во время объединения. В этом примере вы вызываете .join() в строке, состоящей из одного символа пробела (" "), таким образом, исходные строки из greeting в вашей конечной строке разделены пробелами.

Заключение

Теперь вы можете использовать встроенную функцию Python sum() для добавления нескольких числовых значений вместе. Эта функция предоставляет эффективный, читаемый и основанный на Python способ решения задач суммирования в вашем коде. Если вы имеете дело с математическими вычислениями, требующими суммирования числовых значений, то sum() может стать вашим спасением.

В этом руководстве вы узнали, как:

  • Суммируйте числовые значения, используя общие методы и инструменты
  • Эффективно добавьте несколько числовых значений, используя Python sum()
  • Объединяйте последовательности, используя sum()
  • Используйте sum() для решения общих задач суммирования
  • Используйте соответствующие значения для аргументов iterable и start в sum()
  • Выберите между sum() и альтернативными инструментами для суммирования и объединения объектов

Обладая этими знаниями, вы теперь можете добавлять несколько числовых значений вместе понятным и эффективным способом на языке Python.

<статус завершения article-slug="python-sum-function" class="btn-group mb-0" data-api-article-bookmark-url="/api/v1/articles/python-sum-function/bookmark/" data-api-article-завершение-status-url="/api/v1/articles/python-sum-функция/завершение_статуса/"> <кнопка поделиться bluesky-text="Интересная статья на #Python от @realpython.com :" email-body="Ознакомьтесь с этой статьей на Python:%0A%0apython's sum(): Способ суммирования значений на языке Python" email-subject="Статья на Python для вас" twitter-text="Интересная статья на #Python от @realpython:" url="https://realpython.com/python-sum-function/" url-title="Python's sum(): способ суммирования значений на языке Python">

Смотрите сейчас, к этому уроку прилагается соответствующий видеокурс, созданный командой Real Python. Посмотрите его вместе с письменным руководством, чтобы углубить свое понимание: Суммирование значений по-питонски с помощью sum()

Back to Top