How does Python's comma operator work during assignment? - python

I was reading the assignment statements in the Python docs ( http://docs.python.org/reference/simple_stmts.html#assignment-statements).
In that it is quoted that:
If the target is a target list enclosed in parentheses or in square brackets: The object must be an iterable with the same number of items as there are targets in the target list, and its items are assigned, from left to right, to the corresponding targets.
After reading it, I thought of writing a sample like this:
a = 5
b = 4
a, b = a + b, a
print a, b
My assumption was that a and b both should have the value of 9.
However, I am proven wrong. 'a' has the value of 9 and 'b' has the value of 5.
Can some one help me understand this better? Why the older value of 'a' is assigned rather than the new one? As per the docs, a's value will be assigned first right? Am I missing something?

All the expressions to the right of the assignment operator are evaluated before any of the assignments are made.
From the Python tutorial: First steps towards programming:
The first line contains a multiple assignment: the variables a and b simultaneously get the new values 0 and 1. On the last line this is used again, demonstrating that the expressions on the right-hand side are all evaluated first before any of the assignments take place. The right-hand side expressions are evaluated from the left to the right.
Emphasis mine.
Your code is functionally equivalent to the following:
a, b = 5 + 4, 5
print a, b

Python does not have a "comma operator" as in C. Instead, the comma indicates that a tuple should be constructed. The right-hand side of
a, b = a + b, a
is a tuple with th two items a + b and a.
On the left-hand side of an assignment, the comma indicates that sequence unpacking should be performed according to the rules you quoted: a will be assigned the first element of the tuple, b the second.

You can think of the assignments happening in parallel on copies rather than sequentially and in-place.
This is why in python you dont need a swap function:
a, b = b, a
works sufficiently without requiring a temp variable, c.

Related

How to combine 3 variables. Pretty simple

I have a problem that asks me to combine three numeric variables, for example, a = 1 , b = 2 , c = 3. We're supposed to make d = ' 1|2|3 '. I've done some scripting in BASH where "|" refers to piping. How would you accomplish this in Python, and what does "|" mean?
The vertical bar is merely a character. Treat this the same way you would a comma or a dash. Convert each integer to string, and concatenate them with the bar in between. This is merely an exercise in string manipulation; nothing particularly deep or tricky.
Not sure what exactly you are expected to do or mean by "combining". In Python you can combine variables into tuples so that you can have a "compound" or combined variable that you can use for lookup tables, etc.
a = 1
b = 2
c = 3
combined = (a,b,c)
now you can do things like x = {combined: "value"}
The solution hspandher is on the right track, but would work primarily for one set of three numeric variables. It might be more useful to create a function like this:
def numberCombiner(a, b, c):
return str(a)+"|"+str(b)+"|"+str(c)
numberCombiner(1,2,3)
Which would take in three numeric values and output the string you want. Then you can call/invoke the numberCombiner function on different values, like:
numberCombiner(2,3,4)
which would return
>>> '2|3|4'
Using format:
>>> a=1
>>> b=2
>>> c=3
>>> "{}|{}|{}".format(a,b,c)
'1|2|3'
Just create a list of all the variables, and join them using the pipe symbol.
"|".join(map(str, [a, b, c]))
Use a generator expression to convert your integer variables into strings, and join them with the vertical line symbol.
"|".join(str(v) for v in [a, b, c])
More about generator expression.
More about string joining.
Thanks to juanpa.arrivillaga for pointing out the generator expression syntax where the generator is used right away by an enclosing function. See comments for more information.

Python and assignment [duplicate]

This question already has answers here:
List assignment to other list
(3 answers)
Closed 5 years ago.
I'm trying to understand (on the level of principle) the difference between assignment between (say) integers variables and list variables.
Integer case:
a=6
b=a
print(b) #prints 6
a=7
print(b) #prints 6
That makes sense to me with this logic: in the original b=a, b was given the same value as a (6), not identified with a. So if I change the value of a, the value of b does not change: b is not the same thing as a.
List case:
L=[1,2]
M = L
print(M)
L.append(6)
print(M)
This can make sense with this logic: in M=L I'm forcing M to literally be the same object as L is, I'm identifying it with L. So if L changes, so does M.
What doesn't make sense (to me) is why I need different logic in different cases. (Probably this has to do with integers being "immutable" and lists "mutable" but I don't see how that bears on this.) Can someone point me to a explanation? What is the principle behind the difference in behaviors? (I'm not looking so much for how the technical difference in implementation of integers and lists leads to the difference, but for the reason things were designed this way. What's the logic?)
Every name is a variable holding a reference to some object.
What happens in the first case is that
a = 6
b = a # (a and b point to the same object)
But here, you are changing what a points to:
a = 7
Compare this to the second/list situation, where you actually call the method on the first object. You didn't update the reference as you did in the case with the integers.
L = [1,2]
M = L # here you introduce a new name, referencing the same object as L.
L.append(6) # update that same object.
print(M) # you print that same object
You don't have different logic in different cases here. Lists and integers work in exactly the same way as far as assignment is concerned. If, in your second snippet, to assigned a different list to L in the penultimate line, the two variables would be unrelated.
But lists have an additional capability, which integers and strings don't have, which is that you can modify them. That's all you're​ seeing here.
Well M = L gets what L currently is and after it prints M you then append 6 to L but this will only effect L because M had only received what L previously was, but if you did M = L again after the append it would print the updated version of the list. Basically if you get a xvariable set to a yvariable and then that yvariable updates the xvariable will not update because you will have to update the xvariable again but this is usually this happens by it self if a loop is being used

Is python tuple assignment order fixed?

Will
a, a = 2, 1
always result in a equal to 1? In other words, is tuple assignment guaranteed to be left-to-right?
The matter becomes relevant when we don't have just a, but a[i], a[j] and i and j may or may not be equal.
Yes, it is part of the python language reference that tuple assignment must take place left to right.
https://docs.python.org/2.3/ref/assignment.html
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.
So all Python implementations should follow this rule (as confirmed by the experiments in the other answer).
Personally, I would still be hesitant to use this as it seems unclear to a future reader of the code.
How it works :
a, a = 2, 1
--> a does not exist, create variable a and set value to 2
--> a already exists, value of a changed to 1
When you have different variables, it works exactly the same way :
a, b, a = 1, 2, 3
--> a does not exist, create variable a and set value to 1
--> b does not exist, create variable b and set value to 2
--> a already exists, value of a changed to 3

Using strings form list inside a loop as variables

This is newbie question. I am working on something called sagemath which is completely based on Python.
My code is two parts:
The first part is:
var('a,b')
my_list=list(powerset([a,b]))
my_possible_products_list=[]
for i in my_list:
if len(i)!=0:
my_possible_products_list.append(prod(i))
print my_possible_products_list
with an ouput
[a, b, a*b]
i.e, the result is a list of all possible product expressions on a set of two variables.
The second part:
for expression_compute in my_possible_products_list:
for l in range(1,3):
for a in divisors(l):
for b in divisors(l):
print expression_compute
with an output
a
a
a
a
a
b
b
b
b
b
a*b
a*b
a*b
a*b
a*b
The problem: I need to have numerical output, not using a and b, but using the values of a and b as divisors of the given l.
Any hint?
Thanks.
Not sure if I understand the question here, but to my understanding you have the expression as a string and want to compute the value. For a and b as single entities it's easy, just cast to integer
a = "5"
print(int(a) + 1) # Will print 6
for the product expression you could do as #iForest suggests using eval() but as he said that is evil. I would use the split method
expr = "3*5"
terms = expr.split('*')
print(int(terms[0]) * int(terms[1])) # Will print 15
hope this helps, otherwise I need more explanation of your problem
== Updates after #iForest comment ==
If it is the variables names as strings that are needed use locals()
a = 3
b = 5
variables = locals()
expr = "a*b"
terms = expr.split('*')
print(variables[terms[0]] * variables[terms[1]]) # Output 15
will work as long as you don't need to update the variables
Built-in function eval() can evaluate value of string.
a = 3
b = 5
print(eval("a * b")) # Output 15
But yes, eval() is EVIL.
It's easy and quick to use, but be careful when you use it. You have to make sure the input string you eval() is OK. Read more about how to use / how dangerous here (8.9. Evaluating Arbitrary Strings As Python Expressions).

Consecutive assignments in python

Is it legal to do
a = b = 3
in python? If so, is it a bad practice?
Yes, it is legal to do so. No, it is not bad practice.
Just take into account that the right-hand side, the value expression, is evaluated first, and assignment then takes place from left to right; 3 is assigned to a first, then to b.
From the assignment statement documentation:
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.
You assign the same value to all targets. That means that each variable refers to one value only. This is important when that value is mutable, like a list or a dictionary.
Yes, just watch out for stuff like this:
a = b = []
a.append(2)
print a
print b
Prints:
[2]
[2]
But other than that, it's fine. #Martijn has a lot of information in his answer, so check it out :).

Categories

Resources