Как я могу умножить все элементы в списке вместе с Python?

204

Мне нужно написать функцию, которая берет список чисел и умножает их вместе. Пример: [1,2,3,4,5,6]даст мне 1*2*3*4*5*6. Я мог бы действительно использовать вашу помощь.

user1897814
источник

Ответы:

208

Python 3: использовать functools.reduce:

>>> from functools import reduce
>>> reduce(lambda x, y: x*y, [1,2,3,4,5,6])
720

Python 2: использовать reduce:

>>> reduce(lambda x, y: x*y, [1,2,3,4,5,6])
720

Для совместимости с 2 и 3 использованием pip install six, тогда:

>>> from six.moves import reduce
>>> reduce(lambda x, y: x*y, [1,2,3,4,5,6])
720
богатый слой
источник
Вы не импортируете оператора, поэтому это решение немного более компактно. Интересно, что быстрее.
Джелд
30
@jheld: я рассчитал число от 1 до 100. В обоих python2 и 3 lambdaзанял в среднем 0,02 с / 1000 повторений, в то время как operator.mulв среднем 0,009 с / 1000 повторений, что operator.mulна порядок быстрее.
Whereswalden
4
@wordsforhewise, вероятно, это то, что прохождение дополнительной функции (лямбда) добавляет накладные расходы, в то время как operator.mulидет прямо к C.
Whereswalden
4
Я действительно не назвал бы .009 на порядок ниже, чем .02. Это примерно половина.
июля
1
Начиная с Python 3.8 это можно сделать просто с помощью math.prod([1,2,3,4,5,6]). (требуется импорт конечно)
Томерикоо
168

Ты можешь использовать:

import operator
import functools
functools.reduce(operator.mul, [1,2,3,4,5,6], 1)

Смотрите reduceи operator.mulдокументацию для объяснения.

Вам нужна import functoolsстрока в Python 3+.

icecrime
источник
32
Обратите внимание, что в python3 reduce()функция была удалена из глобального пространства имен и помещена в functoolsмодуль. Так что в python3 вам нужно сказать from functools import reduce.
Евгений Ярмаш
2
«1» в качестве третьего аргумента здесь не нужен, в каком случае это будет необходимо?
словами
5
@wordsforhewise без третьего аргумента выдает исключение TypeError, если вы передаете ему пустую последовательность
Francisco Couzo
1
lambda x,y: x*yтакже работает вместоoperator.mul
79

Я бы использовал numpy.prodдля выполнения задачи. Увидеть ниже.

import numpy as np
mylist = [1, 2, 3, 4, 5, 6] 
result = np.prod(np.array(mylist))  
belindanju
источник
13
Удобно, если вы уже используете Numpy. Вам, вероятно, даже не нужно сначала приводить его в список, это должно работать в большинстве случаевresult = np.prod(mylist)
Ник
4
Две вещи, на которые следует обратить внимание: 1) Он может переполниться, особенно если используется значение по умолчанию, numpy.int32как указано выше. 2) Для небольших списков это будет значительно медленнее, поскольку NumPy необходимо выделить массив (актуально, если повторяется часто)
Disenchanted
1
переполнение для значений выше 21 здесьnp.prod(np.array(range(1,21)))
PatrickT
Это не хороший выбор. Это может переполниться, и это медленнее. попробуй reduce.
Пейман
57

Если вы хотите избежать импорта чего-либо и избежать более сложных областей Python, вы можете использовать простой цикл for

product = 1  # Don't use 0 here, otherwise, you'll get zero 
             # because anything times zero will be zero.
list = [1, 2, 3]
for x in list:
    product *= x
DeadChex
источник
7
Небольшое примечание: Срезы в Python очень просты, и, поскольку здесь мы имеем дело только с примитивами, вы можете избежать незначительных ошибок, начиная с 1, начиная со list [0] и итерируя по list [1:]. Хотя освоение с более функциональными «уменьшенными» ответами здесь полезно в долгосрочной перспективе, а также полезно в других обстоятельствах.
кунгфу
@kungphu Пустой продукт обычно определяется как 1, вместо этого ваше решение выдает исключение IndexError, если вы передадите ему пустую последовательность
Francisco Couzo
@ Франциско Конечно, но эта функция, вероятно, должна выдать некоторую разновидность исключения в этом случае, поскольку пустая последовательность будет недопустимым вводом для этой функции. Фактически, эта функция не имеет смысла для любой последовательности с менее чем двумя значениями; если вы передадите последовательность с одним значением и умножите ее на 1, вы по существу добавили значение, которого там не было, что, я бы сказал, равносильно неожиданному поведению.
Кунгфу
1
@kungphu, поведение для этого ответа правильное, то есть передача списка длины 1 возвращает значение, а передача списка длины 0 возвращает 1. Он находится в том же направлении, что и сумма ([]) как 0 или сумма ([3]) как 3. См .: en.wikipedia.org/wiki/Empty_product
emorris
Я понимаю вашу точку зрения относительно математических функций. Однако в практической ситуации разработки я бы назвал это очень редкой ситуацией, когда функция, которая явно предназначена для работы с вводом, должна возвращать значение с учетом того, что равнозначно отсутствию ввода или неправильному вводу. Я полагаю, что это зависит от цели упражнения: если это просто репликация стандартной библиотеки, хорошо, возможно, она научит людей кое-чему о том, как (или) язык реализуется или может быть реализован. В противном случае, я бы сказал, что упускается хорошая возможность дать урок о действительных и недействительных аргументах.
кунгфу
14

Начиная Python 3.8, .prodфункция была включена в mathмодуль в стандартной библиотеке:

math.prod(iterable, *, start=1)

Метод возвращает произведение startзначения (по умолчанию: 1) на число итерируемых чисел:

import math
math.prod([1, 2, 3, 4, 5, 6])

>>> 720

Если итерация пуста, это приведет к 1(или startзначению, если оно предоставлено).

Ксавье Гихот
источник
10

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

import functools, operator, timeit
import numpy as np

def multiply_numpy(iterable):
    return np.prod(np.array(iterable))

def multiply_functools(iterable):
    return functools.reduce(operator.mul, iterable)

def multiply_manual(iterable):
    prod = 1
    for x in iterable:
        prod *= x

    return prod

sizesToTest = [5, 10, 100, 1000, 10000, 100000]

for size in sizesToTest:
    data = [1] * size

    timerNumpy = timeit.Timer(lambda: multiply_numpy(data))
    timerFunctools = timeit.Timer(lambda: multiply_functools(data))
    timerManual = timeit.Timer(lambda: multiply_manual(data))

    repeats = int(5e6 / size)
    resultNumpy = timerNumpy.timeit(repeats)
    resultFunctools = timerFunctools.timeit(repeats)
    resultManual = timerManual.timeit(repeats)
    print(f'Input size: {size:>7d} Repeats: {repeats:>8d}    Numpy: {resultNumpy:.3f}, Functools: {resultFunctools:.3f}, Manual: {resultManual:.3f}')

Полученные результаты:

Input size:       5 Repeats:  1000000    Numpy: 4.670, Functools: 0.586, Manual: 0.459
Input size:      10 Repeats:   500000    Numpy: 2.443, Functools: 0.401, Manual: 0.321
Input size:     100 Repeats:    50000    Numpy: 0.505, Functools: 0.220, Manual: 0.197
Input size:    1000 Repeats:     5000    Numpy: 0.303, Functools: 0.207, Manual: 0.185
Input size:   10000 Repeats:      500    Numpy: 0.265, Functools: 0.194, Manual: 0.187
Input size:  100000 Repeats:       50    Numpy: 0.266, Functools: 0.198, Manual: 0.185

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

Разочаровавшись
источник
Вы можете добавить способ
оценки
Я подозреваю , что multiply_functoolsи multiply_numpy отягощено того , чтобы посмотреть на np, functoolsи operatorглобал, с последующими атрибутами поиском. Не могли бы вы перейти на местных жителей? _reduce=functools.reduce, _mul = operator.mul` в сигнатуре функции, затем return _reduce(_mul, iterable)в теле и т. д.
Мартин Питерс
1
Кроме того, версия numy должна сначала преобразовать числа в массив numpy; вы обычно уже сделали бы это преобразование, чтобы включить это в сроки не совсем справедливо. После того, как список преобразован в пустой массив, np.prod()параметр запускается быстрее всего при 100 или более элементах.
Мартин Питерс
8

Мне лично нравится это для функции, которая умножает все элементы общего списка:

def multiply(n):
    total = 1
    for i in range(0, len(n)):
        total *= n[i]
    print total

Он компактен, использует простые вещи (переменную и цикл for) и выглядит для меня интуитивно понятным (похоже, что я думаю о проблеме, просто возьми одну, умножь ее, затем умножь на следующую и так далее! )

user5038135
источник
3
отлично, это самый простой и самый простой.
ghostkraviz
4
for i in n:Тогда почему нет total *= i? не будет ли это намного проще?
Муним Мунна
@MunimMunnaIt не сработало для меня вышеописанным способом.
Атлет
5

Простой способ:

import numpy as np
np.exp(np.log(your_array).sum())
XXinyue
источник
10
а как же простоnp.prod(your_Array)
дашесы
3

Numpyимеет prod()функцию, которая возвращает произведение списка, или, в данном случае, так как оно пустое, это произведение массива по заданной оси:

import numpy
a = [1,2,3,4,5,6]
b = numpy.prod(a)

... или вы можете просто импортировать numpy.prod():

from numpy import prod
a = [1,2,3,4,5,6]
b = prod(a)
Лео Иган
источник
2

Нашел этот вопрос сегодня, но я заметил, что у него нет случая, когда есть Noneв списке. Итак, полное решение будет:

from functools import reduce

a = [None, 1, 2, 3, None, 4]
print(reduce(lambda x, y: (x if x else 1) * (y if y else 1), a))

В случае сложения имеем:

print(reduce(lambda x, y: (x if x else 0) + (y if y else 0), a))
Xxxo
источник
2
nums = str(tuple([1,2,3]))
mul_nums = nums.replace(',','*')
print(eval(mul_nums))
М. Диксон
источник
5
Пожалуйста, добавьте пояснения к вашему ответу. Как ответить
xenteros
3
Я вмешиваюсь и пытаюсь объяснить код: лично мне этот код не очень нравится, поскольку он использует eval, который интерпретирует строку как аргумент или функцию (и, таким образом, обычно рассматривается как небезопасная вещь, особенно при обработке входных данных ). Строка перед этим заменяет каждую запятую с разделителем на мультипликативный *, так что eval распознает это как мультипликативный. Интересно, как обстоят дела с этим, особенно по сравнению с другими решениями
dennlinger
Вау, такая плохая идея!
Ковальский
1

Я хотел бы это следующим образом:

    def product_list(p):
          total =1 #critical step works for all list
          for i in p:
             total=total*i # this will ensure that each elements are multiplied by itself
          return total
   print product_list([2,3,4,2]) #should print 48
Шакти Нандан
источник
1

Это мой код:

def product_list(list_of_numbers):
    xxx = 1
    for x in list_of_numbers:
        xxx = xxx*x
    return xxx

print(product_list([1,2,3,4]))

результат: ('1 * 1 * 2 * 3 * 4', 24)

jackim
источник
0

Как насчет использования рекурсии?

def multiply(lst):
    if len(lst) > 1:
        return multiply(lst[:-1])* lst[-1]
    else:
        return lst[0]
mtdkki
источник
-1

Мое решение:

def multiply(numbers):
    a = 1
    for num in numbers:
        a *= num
        return a

  pass
Дориан Ванзант
источник
-1

'' 'единственный простой способ понять логику, используемую для цикла' ''

Lap = [2,5,7,7,9] x = 1 для i на круге: x = i * x print (x)

Сандип Ратури
источник
Ваш ответ не добавляет ничего нового к обсуждению этого вопроса.
Сид
-3

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

def myfunc(lst):
    multi=1
    for product in lst:
        multi*=product
    return product
Адитья
источник
2
Дублируйте ответ DeadChex, ответ piSHOCK, ответ Shakti Nandan. Не размещайте ответ, который уже предложен.
Муним Мунна
он также должен вернуть несколько | - |
Ларс