2

I'm learning python, use w3schools python tutorial, read about how python "Many Values to Multiple Variables" and confused by the following Casting process.

>>> a=b,c=d = 1,2
>>> print(a,b,c,d)
(1, 2) 1 2 (1, 2)
>>> print(type(a),type(b),type(c),type(d))
<class 'tuple'> <class 'int'> <class 'int'> <class 'tuple'>
>>> x,y,z,t = 1,2,3,4
>>> print(type(x),type(y),type(z),type(t))
<class 'int'> <class 'int'> <class 'int'> <class 'int'>
>>> print(x,y,z,t)
1 2 3 4
>>>

How type of a,d is 'tuple'?

I thought they were 'int' when I study about it.

CMV
  • 21
  • 3
  • `1` and `2` are ints, sure, but that's not what you're assigning to `a` or `d`. Nothing's being cast, automatically or otherwise. – jonrsharpe Apr 27 '22 at 13:56
  • 3
    The tuple `1, 2` is the value being assigned. There are three assignment targets: `a`, `b,c`, and `d`. The first and last of those, being a single name, get the tuple directly; the middle one unpacks the tuple. – jasonharper Apr 27 '22 at 13:57
  • It is obviously impossible for an integer to be both 1 and 2. – Mechanic Pig Apr 27 '22 at 13:57

3 Answers3

4

From the section 7.2 of the language reference, Assignment statements

An assignment statement evaluates the expression list (remember that this can be a single expression or a comma-separated list, the latter yielding a tuple) and assigns the single resulting object to each of the target lists, from left to right.

The first assignment statement

a = b, c = d = 1, 2

^     ^    ^    ^
|     |    |    +-- expression list
|     |    +-- target #3
|     +-- target #2
+-- target #1

consists of the expression list 1, 2 (which evaluates to a tuple) and three targets a, b, c, and d, which are assigned in the following order:

a = 1, 2
b, c = 1, 2
d = 1, 2

There is no casting involved. The assignments to a and d assign the tuple directly; the assignment to b and c pairs each target with a corresponding value in the tuple.


Perhaps most notably, it is not like in C where an assignment is considered an expression whose value is the value that was assigned. Something like a = b = c = d in C is equivalent to

/* C with explicit parentheses
 * d is assigned to c, with the value of c = d assigned
 * to b, and the value of b = c = d assigned to a
 */
a = (b = (c = d))

while in Python it is a single statement with the semantics defined above.

A common idiom in C is to use the value of an assignment in a conditional statement, so that you can bind the value being tested to a variable used later in the same statement.

while ((c = foo()) != bar) {
    printf("%s\n", c)
}

Prior to the introduction of the assignment expression in Python, the equivalent required a separate assignment statement before and in the while statement:

c = foo()
while c != bar:
    print(c)
    c = foo()
    

or more idiomatically, an infinite loop with an explicit break condition

while True:
    c = foo()
    if c == bar:
        break
    print(c)

With the assignment expression, you can now embed an assignment into a boolean-valued expression similar to the C example.

while (c := foo()) != bar:
    print(c)
chepner
  • 497,756
  • 71
  • 530
  • 681
  • I think python never casts anything if not explicitly told – sudden_appearance Apr 27 '22 at 14:08
  • 1
    Depends on what you consider casting. I think of Python as doing *no* casting: it never treats a value of one type as another type. Things like `str(3)` create a *new* `str` object rather than treating the existing `int` object as a string (though there are people who consider such conversions as another kind of cast). Things get murkier when you consider the `print` function (which implicitly calls `str` on its positional arguments) and conditional statements (which implicitly obtain a Boolean value when necessary). Still not a cast in my opinion, but I don't really consider it explicit. – chepner Apr 27 '22 at 14:11
  • Yes, by explicit i mean using `int(), float(), str(), dict(), list(), tuple()` and so on) – sudden_appearance Apr 27 '22 at 14:16
  • I find it interesting how the equal signs in the left-hand-side affect the assignment operation. – wwii Apr 27 '22 at 14:48
  • @wwii I'm not sure I follow. They don't really "affect" it in any way; they just induce *additional* assignments. For example, the presence of the `a = b, c = ` "prefix" doesn't affect the assignment to `d` in any way. – chepner Apr 27 '22 at 15:02
  • @chepner very detailed. Thank you. I'm learning from you guys – CMV Apr 29 '22 at 07:53
0

When you do

a=b,c=d = 1,2

following happens

d = 1,2 # now d is 2-tuple
b,c=d # 2-tuple is unpacked, now b is 1 and c is 2
a=b,c # new 2-tuple a is created using b and c, now a is 2-tuple (1,2)
Daweo
  • 31,313
  • 3
  • 12
  • 25
0

I think it is clearer when you add the () to surround tuples. This

a = (b, c) = d = (1, 2)
print(type(a), type(b), type(c), type(d))
print(a, b, c, d)

is equivalent to

a = b, c = d = 1, 2
print(type(a), type(b), type(c), type(d))
print(a, b, c, d)

So you assign a tuple (1, 2) to three targets a, (b, c) and d from left to right. (b, c) just unpacks the values so b is assigned the first and c assigned the last value of (1, 2). All other variables i. e. a and d just get the tuple (1, 2) assigned.

Mushroomator
  • 6,516
  • 1
  • 10
  • 27