Python assigning multiple variables to same value? list behavior
If you're coming to Python from a language in the C/Java/etc. family, it may help you to stop thinking about a
as a "variable", and start thinking of it as a "name".
a
, b
, and c
aren't different variables with equal values; they're different names for the same identical value. Variables have types, identities, addresses, and all kinds of stuff like that.
Names don't have any of that. Values do, of course, and you can have lots of names for the same value.
If you give Notorious B.I.G.
a hot dog,* Biggie Smalls
and Chris Wallace
have a hot dog. If you change the first element of a
to 1, the first elements of b
and c
are 1.
If you want to know if two names are naming the same object, use the is
operator:
>>> a=b=c=[0,3,5]
>>> a is b
True
You then ask:
what is different from this?
d=e=f=3
e=4
print('f:',f)
print('e:',e)
Here, you're rebinding the name e
to the value 4
. That doesn't affect the names d
and f
in any way.
In your previous version, you were assigning to a[0]
, not to a
. So, from the point of view of a[0]
, you're rebinding a[0]
, but from the point of view of a
, you're changing it in-place.
You can use the id
function, which gives you some unique number representing the identity of an object, to see exactly which object is which even when is
can't help:
>>> a=b=c=[0,3,5]
>>> id(a)
4473392520
>>> id(b)
4473392520
>>> id(a[0])
4297261120
>>> id(b[0])
4297261120
>>> a[0] = 1
>>> id(a)
4473392520
>>> id(b)
4473392520
>>> id(a[0])
4297261216
>>> id(b[0])
4297261216
Notice that a[0]
has changed from 4297261120 to 4297261216—it's now a name for a different value. And b[0]
is also now a name for that same new value. That's because a
and b
are still naming the same object.
Under the covers, a[0]=1
is actually calling a method on the list object. (It's equivalent to a.__setitem__(0, 1)
.) So, it's not really rebinding anything at all. It's like calling my_object.set_something(1)
. Sure, likely the object is rebinding an instance attribute in order to implement this method, but that's not what's important; what's important is that you're not assigning anything, you're just mutating the object. And it's the same with a[0]=1
.
user570826 asked:
What if we have,
a = b = c = 10
That's exactly the same situation as a = b = c = [1, 2, 3]
: you have three names for the same value.
But in this case, the value is an int
, and int
s are immutable. In either case, you can rebind a
to a different value (e.g., a = "Now I'm a string!"
), but the won't affect the original value, which b
and c
will still be names for. The difference is that with a list, you can change the value [1, 2, 3]
into [1, 2, 3, 4]
by doing, e.g., a.append(4)
; since that's actually changing the value that b
and c
are names for, b
will now b [1, 2, 3, 4]
. There's no way to change the value 10
into anything else. 10
is 10 forever, just like Claudia the vampire is 5 forever (at least until she's replaced by Kirsten Dunst).
* Warning: Do not give Notorious B.I.G. a hot dog. Gangsta rap zombies should never be fed after midnight.
Python initialize multiple variables to the same initial value
I agree with the other answers but would like to explain the important point here.
None object is singleton object. How many times you assign None object to a variable, same object is used. So
x = None
y = None
is equal to
x = y = None
but you should not do the same thing with any other object in python. For example,
x = {} # each time a dict object is created
y = {}
is not equal to
x = y = {} # same dict object assigned to x ,y. We should not do this.
More elegant way of declaring multiple variables at the same time
As others have suggested, it's unlikely that using 10 different local variables with Boolean values is the best way to write your routine (especially if they really have one-letter names :)
Depending on what you're doing, it may make sense to use a dictionary instead. For example, if you want to set up Boolean preset values for a set of one-letter flags, you could do this:
>>> flags = dict.fromkeys(["a", "b", "c"], True)
>>> flags.update(dict.fromkeys(["d", "e"], False))
>>> print flags
{'a': True, 'c': True, 'b': True, 'e': False, 'd': False}
If you prefer, you can also do it with a single assignment statement:
>>> flags = dict(dict.fromkeys(["a", "b", "c"], True),
... **dict.fromkeys(["d", "e"], False))
>>> print flags
{'a': True, 'c': True, 'b': True, 'e': False, 'd': False}
The second parameter to dict
isn't entirely designed for this: it's really meant to allow you to override individual elements of the dictionary using keyword arguments like d=False
. The code above blows up the result of the expression following **
into a set of keyword arguments which are passed to the called function. This is certainly a reliable way to create dictionaries, and people seem to be at least accepting of this idiom, but I suspect that some may consider it Unpythonic. </disclaimer>
Yet another approach, which is likely the most intuitive if you will be using this pattern frequently, is to define your data as a list of flag values (True
, False
) mapped to flag names (single-character strings). You then transform this data definition into an inverted dictionary which maps flag names to flag values. This can be done quite succinctly with a nested list comprehension, but here's a very readable implementation:
>>> def invert_dict(inverted_dict):
... elements = inverted_dict.iteritems()
... for flag_value, flag_names in elements:
... for flag_name in flag_names:
... yield flag_name, flag_value
...
>>> flags = {True: ["a", "b", "c"], False: ["d", "e"]}
>>> flags = dict(invert_dict(flags))
>>> print flags
{'a': True, 'c': True, 'b': True, 'e': False, 'd': False}
The function invert_dict
is a generator function. It generates, or yields — meaning that it repeatedly returns values of — key-value pairs. Those key-value pairs are the inverse of the contents of the two elements of the initial flags
dictionary. They are fed into the dict
constructor. In this case the dict
constructor works differently from above because it's being fed an iterator rather than a dictionary as its argument.
Drawing on @Chris Lutz's comment: If you will really be using this for single-character values, you can actually do
>>> flags = {True: 'abc', False: 'de'}
>>> flags = dict(invert_dict(flags))
>>> print flags
{'a': True, 'c': True, 'b': True, 'e': False, 'd': False}
This works because Python strings are iterable, meaning that they can be moved through value by value. In the case of a string, the values are the individual characters in the string. So when they are being interpreted as iterables, as in this case where they are being used in a for loop, ['a', 'b', 'c']
and 'abc'
are effectively equivalent. Another example would be when they are being passed to a function that takes an iterable, like tuple
.
I personally wouldn't do this because it doesn't read intuitively: when I see a string, I expect it to be used as a single value rather than as a list. So I look at the first line and think "Okay, so there's a True flag and a False flag." So although it's a possibility, I don't think it's the way to go. On the upside, it may help to explain the concepts of iterables and iterators more clearly.
Defining the function invert_dict
such that it actually returns a dictionary is not a bad idea either; I mostly just didn't do that because it doesn't really help to explain how the routine works.
Apparently Python 2.7 has dictionary comprehensions, which would make for an extremely concise way to implement that function. This is left as an exercise to the reader, since I don't have Python 2.7 installed :)
You can also combine some functions from the ever-versatile itertools module. As they say, There's More Than One Way To Do It. Wait, the Python people don't say that. Well, it's true anyway in some cases. I would guess that Guido hath given unto us dictionary comprehensions so that there would be One Obvious Way to do this.
How to assign the same value to multiple variables in Python
use the [copy] module
>>> import copy
>>> new_matrix = copy.deepcopy(myMatrix)
Is assigning two variables to items in the same list the best way to access and perform operations on those items?
Python provides built in method
from itertools import product
l = [1,2,3]
Then generate the sum using list comprehension in a single step to be more efficent
result= [sum(i) for i in product(l, repeat= 2) ]
#result=[2, 3, 4, 3, 4, 5, 4, 5, 6]
Related Topics
How to Get Rid of Double Backslash in Python Windows File Path String
How to Resolve Typeerror: Can Only Concatenate Str (Not "Int") to Str
Matplotlib Fill Between Multiple Lines
Does a File Object Automatically Close When Its Reference Count Hits Zero
Pylab.Ion() in Python 2, Matplotlib 1.1.1 and Updating of the Plot While the Program Runs
How to Determine the Language of a Piece of Text
Cannot Install Lxml on MAC Os X 10.9
Running Python on Windows for Node.Js Dependencies
Usage of Sys.Stdout.Flush() Method
Python's Insert Returning None
Pygame.Error: Video System Not Initialized
Paramiko Ssh Die/Hang with Big Output
How to Create Animated Sprites Using Sprite Sheets in Pygame