Is it right to assign multiple variables like this a = b = c = d = 5?
The thing to be aware of here is that your case only works OK because numbers are immutable in Ruby. You don't want to do this with strings, arrays, hashes or pretty much anything else other than numbers, because it would create multiple references to the same object, which is almost certainly not what you want:
a = b = c = d = "test"
b << "x"
=> "testx"
a
=> "testx"
Whereas the parallel form is safe with all types:
a,b,c,d = "test","test","test","test"
=> ["test", "test", "test", "test"]
b << "x"
=> "testx"
a
=> "test"
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.
Multiple variable assignments in one row
The short answer is yes, that statement will assign 5
to each of 4 variables a
, b
, c
and d
. But, contrary to what was said, doesn't assign 5
to d
, and then the value of d
to c
, but it will assign the same value to each variables, starting from the right-hand side. To be more clear, your statement:
var a, b, c, d;
a = b = c = d = 5;
It's equivalent to:
var d = 5;
var c = 5;
var b = 5;
var a = 5;
Not to:
var d = 5;
var c = d;
var b = c;
var a = b;
It's a subtle but important difference: in the first case, JavaScript just sets a value to all the variables. In the second case, JavaScript set a value to all the variables but also get the value of three variables (the value of a
is not assigned anywhere).
A simple code that will show that:
// `this` is the global object if you run this code in the global scope.
// In the browsers the global object is `window`.
Object.defineProperties(this, {
"a": {
get: function() {
console.log("get a");
},
set: function(value) {
console.log("set a");
}
},
"b": {
get: function() {
console.log("get b");
},
set: function(value) {
console.log("set b");
}
},
"c": {
get: function() {
console.log("get c");
},
set: function(value) {
console.log("set c");
}
},
"d": {
get: function() {
console.log("get d");
},
set: function(value) {
console.log("set d");
}
}
});
b = c = d = 5;
a = b;
On the console you should have:
set d
set c
set b
get b
set a
As you can see for the statement b = c = d = 5
JS only set the variable, and call both set
and get
on b
, because the statement a = b
.
This distinction is very important, because if you define some getter for your property and you're not aware of this behavior, you will end up with unexpected bug using multiple variable assignments.
Can I assign multiple variables the same value without having one line per variable/assignment?
You could destructure your variables as an array as follows, though you need to know the number of elements, and it does require ES6+:
let [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o] = Array(15).fill(0);
Assign multiple variables to the same value in Javascript?
Nothing stops you from doing
moveUp = moveDown = moveLeft = moveRight = mouseDown = touchDown = false;
Check this example
var a, b, c;a = b = c = 10;console.log(a + b + c)
The mechanism behind multiple assignment in Python
a, b = c, d
is equivalent to
temp = (c, d)
a = temp[0] # Expression a is evaluated here, not earlier
b = temp[1] # Expression b is evaluated here, not earlier
Personally I would recommend to write complex assignments explicitly with temporary variables as you showed it.
Another way is to carefully choose the order of the elements in the assignment:
nums[nums[0]], nums[0] = nums[0], nums[nums[0]]
Changes nums
as you expect.
Is there a way to assign multiple variables a same value or attribute?
This has already been answered here:
Set multiple variables to the same value in Javascript
in python it would be:
a = b = c = d = e = 'dog'
its the same in javascript but with 'var' at the beginning:
var a = b = c = d = e = 'dog'
Assign two variables to the same value with one expression?
Yes, it is possible:
let x, y;
x = y = 'hi';
It is called chaining assignment, making possible to assign a single value to multiple variables.
See more details about assignment operator.
If you have more than 2 variables, it's possible to use the array destructing assignment:
let [w, x, y, z] = Array(4).fill('hi');
Can you declare multiple variables at once in Go?
Yes, you can:
var a, b, c string
a = "foo"
fmt.Println(a)
You can do something sort of similar for inline assignment, but not quite as convenient:
a, b, c := 80, 80, 80
Related Topics
Rails 4: How to Reset Test Database
Sort Array Returned by Activerecord by Date (Or Any Other Column)
Setting Up the Logger in Rails 3
Ruby - Elegantly Convert Variable to an Array If Not an Array Already
Parse Command Line Arguments in a Ruby Script
How to Handle Constants in Ruby When Using Rails
What's the Difference Between Request.Remote_Ip and Request.Ip in Rails
How to List the Currently Available Objects in the Current Scope in Ruby
Read Input from Console in Ruby
When to Use Struct Instead of Hash in Ruby
Installing Ruby 1.9.1 on Ubuntu
How to Change Hash Keys from 'Symbol's to 'String'S
How to Convert a Comma-Separated String into an Array
Rails Bundler Doesn't Install Gems Inside a Group
How to Create a Ruby Date Object from a String
How to Manage Ruby Threads So They Finish All Their Work
How to Suppress the Output of Return Value in Irb/Rails Console