Làm cách nào tôi có thể nhân tất cả các mục trong danh sách cùng với Python?


204

Tôi cần phải viết một hàm lấy danh sách các số và nhân chúng lại với nhau. Ví dụ: [1,2,3,4,5,6]sẽ cho tôi 1*2*3*4*5*6. Lẽ ra tôi đã có thể nhận sự trợ giúp của anh.

Câu trả lời:


208

Python 3: sử dụng functools.reduce:

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

Python 2: sử dụng reduce:

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

Để tương thích với 2 và 3 sử dụng pip install six, sau đó:

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

Bạn không nhập toán tử, vì vậy giải pháp này nhỏ gọn hơn một chút. Tôi tự hỏi cái nào nhanh hơn.
giữ

30
@jheld: Tôi hẹn giờ sản phẩm-ing những con số từ 1 đến 100. Trong cả hai python2 và 3, lambdamất trung bình .02s / 1000 lặp lại, trong khi operator.mulmất trung bình .009s / 1000 lặp lại, làm operator.multheo độ nhanh hơn.
theo đó,

4
@wordsforthewise có lẽ là thông qua một chức năng bổ sung (lambda) thêm chi phí hoạt động, trong khi operator.mulđi thẳng đến C.
theo đó

4
Tôi thực sự sẽ không gọi 0,009 một thứ tự cường độ thấp hơn 0,02. Nó chỉ khoảng một nửa.
jlh

1
Kể từ Python 3.8, nó có thể được thực hiện đơn giản với math.prod([1,2,3,4,5,6]). (yêu cầu nhập khóa học)
Tomerikoo

168

Bạn có thể dùng:

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

Xem reduceoperator.multài liệu cho một lời giải thích.

Bạn cần import functoolsdòng trong Python 3+.


32
Lưu ý rằng trong python3, reduce()hàm đã bị xóa khỏi không gian tên toàn cục và được đặt trong functoolsmô-đun. Vì vậy, trong python3 bạn cần phải nói from functools import reduce.
Eugene Yarmash

2
Ở đây, "1" là đối số thứ ba là không cần thiết, đây là trường hợp cần thiết?
lời giới thiệu

5
@wordsforthewise không có đối số thứ ba, nó sẽ ném ngoại lệ TypeError nếu bạn vượt qua nó một chuỗi trống
Francisco Couzo

1
lambda x,y: x*ycũng hoạt động thay vìoperator.mul

78

Tôi sẽ sử dụng numpy.prodđể thực hiện nhiệm vụ. Xem bên dưới.

import numpy as np
mylist = [1, 2, 3, 4, 5, 6] 
result = np.prod(np.array(mylist))  

13
Thuận tiện nếu bạn đã sử dụng Numpy. Bạn có thể thậm chí không cần phải đưa nó vào danh sách trước, điều này sẽ hoạt động trong hầu hết các trường hợpresult = np.prod(mylist)
Nick

4
Hai điều cần chú ý: 1) Nó có thể tràn, đặc biệt là nếu sử dụng mặc định numpy.int32như trên 2) Đối với danh sách nhỏ này sẽ chậm hơn đáng kể, vì NumPy cần phải phân bổ một mảng (có liên quan nếu lặp đi lặp lại thường xuyên)
Disenchanted

1
tràn cho các giá trị trên 21 ở đây np.prod(np.array(range(1,21)))
PatrickT

Nó không phải là một lựa chọn tốt. Nó có thể tràn và chậm hơn. thử reduce.
Peyman

57

Nếu bạn muốn tránh nhập bất cứ thứ gì và tránh các khu vực phức tạp hơn của Python, bạn có thể sử dụng một vòng lặp đơn giản cho

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

7
Lưu ý nhỏ: Các lát cắt trong Python rất dễ dàng và vì chúng ta chỉ xử lý các nguyên hàm ở đây, nên bạn có thể tránh được các lỗi nhỏ bắt đầu bằng 1 bằng cách bắt đầu với danh sách [0] và lặp qua danh sách [1:]. Mặc dù cảm thấy thoải mái với các câu trả lời 'giảm' nhiều chức năng hơn ở đây về lâu dài có giá trị vì nó cũng hữu ích trong các trường hợp khác.
kungphu

@kungphu Sản phẩm trống thường được định nghĩa là 1, giải pháp của bạn sẽ đưa ra một ngoại lệ IndexError thay vào đó nếu bạn vượt qua nó một chuỗi trống
Francisco Couzo

@Francisco Được cấp, nhưng chức năng này có thể sẽ tạo ra một số ngoại lệ trong trường hợp đó, vì một chuỗi trống sẽ là đầu vào không hợp lệ cho chức năng này. Trong thực tế, hàm này không có ý nghĩa đối với bất kỳ chuỗi nào có ít hơn hai giá trị; nếu bạn truyền một chuỗi với một giá trị và nhân nó với 1, về cơ bản bạn đã thêm một giá trị không có ở đó, điều mà tôi muốn nói là số tiền cho hành vi không mong muốn.
kungphu

1
@kungphu, hành vi cho câu trả lời này là chính xác, tức là chuyển danh sách độ dài 1 trả về giá trị và chuyển danh sách độ dài 0 trả về 1. Nó nằm trong cùng một dòng suy nghĩ cho tổng ([]) là 0 hoặc tổng ([3]) là 3. Xem: en.wikipedia.org/wiki/Empty_product
emorris

Tôi thấy quan điểm của bạn về các chức năng toán học. Tuy nhiên, trong một tình huống phát triển thực tế, tôi sẽ gọi đó là một tình huống rất hiếm khi một hàm rõ ràng hoạt động trên đầu vào sẽ trả về một giá trị được đưa ra với số tiền không có đầu vào hoặc đầu vào không hợp lệ. Tôi cho rằng nó phụ thuộc vào mục tiêu của bài tập: Nếu chỉ là sao chép thư viện chuẩn, OK, có lẽ nó dạy cho mọi người điều gì đó về cách ngôn ngữ (hoặc a) được hoặc có thể được thực hiện. Mặt khác, tôi nói rằng nó bỏ lỡ một cơ hội tốt để cung cấp một bài học về các đối số hợp lệ và không hợp lệ.
kungphu

14

Bắt đầu Python 3.8, một .prodchức năng đã được đưa vào mathmô-đun trong thư viện chuẩn:

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

Phương thức trả về sản phẩm của một startgiá trị (mặc định: 1) nhân với số lần lặp:

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

>>> 720

Nếu iterable trống, điều này sẽ tạo ra 1(hoặc startgiá trị, nếu được cung cấp).


10

Đây là một số phép đo hiệu suất từ ​​máy của tôi. Có liên quan trong trường hợp điều này được thực hiện cho các đầu vào nhỏ trong một vòng lặp dài:

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}')

Các kết quả:

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

Bạn có thể thấy rằng Numpy chậm hơn một chút trên các đầu vào nhỏ hơn, vì nó phân bổ một mảng trước khi phép nhân được thực hiện. Ngoài ra, xem ra cho tràn trong Numpy.


Bạn có thể thêm cách thức chỉ vì tò mò
Mr_and_Mrs_D 27/03/18

Tôi nghi ngờ rằng multiply_functoolsmultiply_numpy đang bị đè nặng bởi phải tìm kiếm các np, functoolsoperatorglobals, tiếp theo là tra cứu thuộc tính. Bạn có phiền khi chuyển sang người địa phương? _reduce=functools.reduce, _mul = oper.mul` trong chữ ký hàm sau đó return _reduce(_mul, iterable)trong cơ thể, v.v.
Martijn Pieters

1
Ngoài ra, phiên bản numpy trước tiên phải chuyển đổi các số thành một mảng numpy; thông thường bạn đã thực hiện chuyển đổi đó, để bao gồm rằng trong thời gian không thực sự công bằng. Với danh sách được chuyển đổi thành một mảng numpy một lần, np.prod()tùy chọn bắt đầu trở nên nhanh nhất ở 100 phần tử trở lên.
Martijn Pieters

8

Cá nhân tôi thích điều này cho một hàm nhân tất cả các thành phần của danh sách chung với nhau:

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

Nó nhỏ gọn, sử dụng những thứ đơn giản (một biến và một vòng lặp for) và cảm thấy trực quan với tôi (có vẻ như tôi nghĩ về vấn đề này, chỉ cần lấy một, nhân nó, sau đó nhân lên tiếp theo, v.v. )


3
tuyệt vời, nó đơn giản nhất và đơn giản nhất.
ghostkraviz 15/03/2017

4
Tại sao không for i in n:, sau đó total *= i? nó sẽ không đơn giản hơn nhiều?
Munim Munna

@MunimMunna Nó không làm việc cho tôi theo cách trên.
vận động viên

5

Cách đơn giản là:

import numpy as np
np.exp(np.log(your_array).sum())

10
những gì về chỉnp.prod(your_Array)
bảnh bao

3

Numpyprod()chức năng trả về sản phẩm của một danh sách hoặc trong trường hợp này vì nó không rõ ràng, đó là sản phẩm của một mảng trên một trục nhất định:

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

... Hoặc nếu không bạn chỉ có thể nhập numpy.prod():

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

2

Tìm thấy câu hỏi này ngày hôm nay nhưng tôi nhận thấy rằng nó không có trường hợp có Nonetrong danh sách. Vì vậy, giải pháp hoàn chỉnh sẽ là:

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

Trong trường hợp bổ sung, chúng tôi có:

print(reduce(lambda x, y: (x if x else 0) + (y if y else 0), a))

2
nums = str(tuple([1,2,3]))
mul_nums = nums.replace(',','*')
print(eval(mul_nums))

5
Vui lòng thêm một số lời giải thích cho câu trả lời của bạn. Cách trả lời
xenteros

3
Tôi kêu gọi và cố gắng giải thích mã: Cá nhân tôi thích mã này không nhiều, vì nó sử dụng eval, nó diễn giải chuỗi là một đối số hoặc hàm (và do đó thường được xem là một việc không an toàn, đặc biệt là khi xử lý dữ liệu đầu vào ). Dòng trước đó thay thế mỗi dấu phẩy phân cách bằng một số nhân *, như vậy eval sẽ nhận ra đây là một số nhân. Tôi tự hỏi làm thế nào hiệu suất về điều này, đặc biệt là so với các giải pháp khác
dennlinger

Wow, thật là một ý tưởng tồi!
Cửu Long

1

Tôi muốn điều này theo cách sau:

    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

Đây là mã của tôi:

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]))

kết quả: ('1 * 1 * 2 * 3 * 4', 24)


0

Làm thế nào về việc sử dụng đệ quy?

def multiply(lst):
    if len(lst) > 1:
        return multiply(lst[:-1])* lst[-1]
    else:
        return lst[0]

-1

Giải pháp của tôi:

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

  pass

-1

'' 'phương pháp đơn giản duy nhất để hiểu cách sử dụng logic cho vòng lặp' ''

Lập = [2,5,7,7,9] x = 1 cho i trong Lập: x = i * x in (x)


Câu trả lời của bạn không thêm bất cứ điều gì mới vào cuộc thảo luận về câu hỏi này.
Sid

-3

Nó rất đơn giản không nhập bất cứ thứ gì. Đây là mã của tôi. Điều này sẽ xác định một chức năng nhân tất cả các mục trong danh sách và trả về sản phẩm của họ.

def myfunc(lst):
    multi=1
    for product in lst:
        multi*=product
    return product

2
Sao y vào câu trả lời của DeadChex, câu trả lời của piSHOCK, câu trả lời của Shakti Nandan. Không đăng câu trả lời đã được đề xuất.
Munim Munna

nó cũng sẽ trả về multi | - |
Lars
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.