Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python syntax detail when multiplying a tuple

Tags:

python

I tried to create a tuple containing two float number. (4.0, 4.0), for example. However, as the two floats was the same, I wrote 4.0, * 2.

What I wanted to do can be written: (4.0,) * 2. In Python, multiply a tuple by an integer says to Python to concatenate this number of times the tuple with itself. So (4.0,) * 2 = (4.0,) + (4.0,) = (4.0, 4.0). OK.

What I did not want to do is 4.0 * 2 (without the comma). Indeed, this will multiply the float 4.0 itself by 2: 4.0 * 2 = 8.0. OK.

But none of these comportments happened. Instead of 8.0 or (4.0, 4.0), I got a

TypeError: 'int' object is not iterable

I am pretty surprized by this answer. How this syntax can lead to an iteration of 2 (which is the sole integer of this expression)?

like image 260
audeoudh Avatar asked Dec 09 '25 17:12

audeoudh


1 Answers

It is matter of precedence, mixed with a wrong operator interpretation.

* (a multiplication) has a higher precedence than ,: 4.0, 4.0 * 2 = 4.0, (4.0 * 2) = (4.0, 8.0). In my expression, it cannot be understood as this, because nothing can be multiplyed by two: 4.0, <nothing> * 2. As a multiplication is a binary operator, it must have a value to the left, which must be 4.0, itself.

This is quite true… for the binary * operator. However, Python has a unary * operator, whose precedence is also higher than ,. This unary operator is used to expand an iterable in-place. This is often seen when we define or call a function with a variable number of arguments:

def min(first, *others): ...
data = tuple(4, 5, 6, 7)
min(*data)

It is this operator that is used in my expression. Python interprets 4.0, * 2 as 4.0, (*2), which says “a tuple, containing 4.0 as first element, followed by all elements contained in 2”. Effectively, an integer is not iterable, and Python complains about it.

As proof, we can compute this expression, which actually gives an iterable to the * unary operator:

>>> 4.0 , * ( 5.0 , 6.0 )  # equivalent of  (4.0, (*(5.0, 6.0)))
(4.0, 5.0, 6.0)
like image 57
audeoudh Avatar answered Dec 11 '25 05:12

audeoudh



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!