Reputation: 268
I had this Python 2.7 code which queries the movement limits from a device:
pan_low_limit = int(self.send_query("PN", 2))
pan_high_limit = int(self.send_query("PX", 2))
tilt_low_limit = int(self.send_query("TN", 2))
tilt_high_limit = int(self.send_query("TX", 2))
I thought I could write this nicer as:
limits = [(pan_low_limit, "PN"), (pan_high_limit, "PX"), (tilt_low_limit, "TN"), (tilt_high_limit, "TX")]
for v, c in limits:
v = int(self.send_query(c, 2))
print("Result from {}: {}".format(c, v))
print(limits)
print("tilt_low_limit: {}".format(tilt_low_limit))
Print statements are to find what's going on. When I run this, I get the following output (these four variables had been initialized with value 1 before this piece of code):
Result from PN: -27067
Result from PX: 27067
Result from TN: -27999
Result from TX: 9333
[(1, 'PN'), (1, 'PX'), (1, 'TN'), (1,'TX')]
tilt_low_limit: 1
PN: 1
I don't really get what's going on. It seems like the value of v in "v = int(self.send_query(c, 2))"
is what I'd expect, but at the next line, these variables have the old values again?
Upvotes: 0
Views: 3200
Reputation: 847
In Python a symbolic name (like pan_low_limit
in your code) is a reference to a value (like "-27067").
When one name is assigned to the other (as happens for limits
and v
in your code), the new name becomes an additional reference to that value. In your case, in the first iteration right before the assignment, the names: pan_low_limit
, limits[0][0]
and v
all refer to the same value:
However, when you assign (or bind) a name to a new value, only that name will refer to the new value. In your case, after the assignment, you will have:
To obtain the result that you want, you should change the variable, instead of reassigning it, so that all the references will refer to the same new value. However, integers are immutable in Python, so you cannot change it. The solution is to use something that is mutable, a list for example.
If you had a mutable variable, the original value could be changed to have the result that you are expecting. You can see this difference in the following two snippets:
Using integers:
pan_low_limit = 1
pan_high_limit = 1
tilt_low_limit = 1
tilt_high_limit = 1
limits = [(pan_low_limit, "PN"), (pan_high_limit, "PX"), (tilt_low_limit, "TN"), (tilt_high_limit, "TX")]
for v, c in limits:
v = 2
print("Result from {}: {}".format(c, v))
print(limits)
print("tilt_low_limit: {}".format(tilt_low_limit))
Result:
Result from PN: 2
Result from PX: 2
Result from TN: 2
Result from TX: 2
[(1, 'PN'), (1, 'PX'), (1, 'TN'), (1, 'TX')]
tilt_low_limit: 1
Using lists, we can modify the value, instead of reassigning it:
pan_low_limit = [1]
pan_high_limit = [1]
tilt_low_limit = [1]
tilt_high_limit = [1]
limits = [(pan_low_limit, "PN"), (pan_high_limit, "PX"), (tilt_low_limit, "TN"), (tilt_high_limit, "TX")]
for v, c in limits:
v[0] = 2
print("Result from {}: {}".format(c, v))
print(limits)
print("tilt_low_limit: {}".format(tilt_low_limit))
Result:
Result from PN: [2]
Result from PX: [2]
Result from TN: [2]
Result from TX: [2]
[([2], 'PN'), ([2], 'PX'), ([2], 'TN'), ([2], 'TX')]
tilt_low_limit: [2]
Reference: link
Thanks @bruno desthuilliers for pointing out flaws in a previous answer.
Upvotes: 0
Reputation: 2147
This is what you want:
for i, (v, c) in enumerate(limits):
limits[i] = int(self.send_query(c, 2))
v =
does not change the value in limits
, it merely changes the value of the reference/variable v
.
Upvotes: 1