0

I have written the following Python code:

numbers = [42, 4224, 42422424, -250]
products = numbers*157
products

This leads to the following output:

42,
 4224,
 42422424,
 -250,
 42,
 4224,
 42422424,
 -250,
 42,
 4224,
 42422424,
 -250,

etc: this order is repeated several times, probably 157 times.

Why does this code not multiply each of the array elements with 157? This should be:

[6594, 663168, 6660320568, -39250]
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
pythonlearner
  • 57
  • 2
  • 11
  • 1
    That's what `*` does in a list context. You probably wanted `products = [x * 157 for x in numbers]` – Nick Jan 31 '20 at 02:13
  • 1
    If you want that behavior try the module `numpy``. It's fabulous for that sort of thing and for many others. – Mike O'Connor Jan 31 '20 at 02:16
  • 1
    That would work for numpy array i.e. `(np.array([42, 4224, 42422424, -250])*157` produces the desired result – DarrylG Jan 31 '20 at 02:17
  • *"Array multiplication multiplies occurence of values instead of values itself"* - correct. It does. And that is why it doesn't do what you want. – kaya3 Jan 31 '20 at 03:34
  • Ask yourself: what does it mean to multiply a number with a list? You might want the answer to be "it should multiply that number with every element of the list". But what if the list doesn't just have numbers in it? If you think about it, you'll find that getting 157 copies of the original list in a single list makes a bit more sense, although this is a bit surprising as well. At least it always means the same thing, regardless of the contents of the list. – Grismar Jan 31 '20 at 04:03

3 Answers3

2

Multiplying a list by any constant c will repeat the elements in the list by a c number of times.

To better understand what's going on here, you should start by multiplying the list by a smaller constant and eventually work your way up to 157. Let's start by multiplying the list by 1:

products = numbers*1
print(products)                                                         
[42, 4224, 42422424, -250]

We can see that multiplying the list by 1 will just send us back our original list, since the elements are only included once in the list. Next, we'll multiply the list by 2:

products = numbers*2
print(products)                                                        
[42, 4224, 42422424, -250, 42, 4224, 42422424, -250]

We can see that the elements are repeated twice in the same list. You can increase the constant on your own to observe the increased amount of repetition.


As others have suggested, you can simply use either list comprehension or numpy arrays to retrieve your desired output:

Method 1: List Comprehension

products = [i*157 for i in numbers]
print(products)                                                        
[6594, 663168, 6660320568, -39250]

List comprehension is essentially shorthand for writing a loop that multiplies each individual element by 157, in our situation.

Method 2: Numpy Arrays

products = np.array(numbers)*157
print(products)
array([6594, 663168, 6660320568, -39250])

Numpy is a module used for array-processing and data manipulation. You can read more about the benefits of numpy here.

Performance Testing

I'll include some performance differences below. This is also a good example that includes multiplying a list by a constant and multiplying its elements by a constant.

>>> timeit.timeit('[i*157 for i in numbers]', 'numbers=[42, 4224, 42422424, -250]', number=1000000)
0.35015837100013414
>>> timeit.timeit('numbers*157', 'import numpy as np;numbers=np.array([42, 4224, 42422424,-250])', number=1000000)
0.639420188000031
>>> timeit.timeit('[i*157 for i in numbers]', 'numbers=[42, 4224, 42422424,-250]*500', number=1000000)
91.96342155899993
>>> timeit.timeit('numbers*157', 'import numpy as np;numbers=np.array([42, 4224, 42422424,-250]*500)', number=1000000)
1.3476544480001849

Typically, numpy arrays are known to perform better than ordinary Python lists for larger array-like data. However, there are certain instances where Python lists can perform better than numpy arrays, which you can read more about here.

dkhara
  • 695
  • 5
  • 18
1

Why does this code not multiply each of the array elements with 157?

You've already got an excellent answer about how to solve your problem of multiplying the numbers in a list by 157. I'll try to address the question of why numbers * 157 behaves the way that it does in Python, rather than the way you think it should.

Being able to repeat the sequence in a list to create a new, longer list is rather useful for initialising a list with some constant initial value. For example, if you want a list of 100 zeroes, you can write [0] * 100. This is a common thing to want to do, so Python makes it easy, and if you read a lot of Python code then you'll become familiar with this "idiom". You might also see for example [None] * 100 to create a list populated with None values.

That second example raises another point; lists in Python can contain any type of data, not just numbers. It would be strange if Python's lists privileged numbers in some way, by having operations which only worked when the list elements were numbers. For example, the expression ['hello', 'world'] * 10 would be an error if this * meant multiplication of numbers.

Another good reason for the behaviour of * on lists is to be consistent with the behaviour of +. In Python when you have two lists and you write list1 + list2, the result will be a new list containing everything in list1 followed by everything in list2. This is called concatenation, and it is very common to want to concatenate lists or other sequences, so Python makes it easy. Given this, it makes sense that numbers + numbers should mean the same thing as numbers * 2; both expressions create a list containing everything from the list numbers, twice.

kaya3
  • 47,440
  • 4
  • 68
  • 97
0

What you want to do is achieved by numpy arrays. In a normal list array, doing numbers * 157 will do the repetition that you obtained. For your desired output,

import numpy as np
products = np.array(numbers) * 157

This outputs

array([      6594,     663168, 6660320568,     -39250])
Swati Srivastava
  • 1,102
  • 1
  • 12
  • 18