I was working with queue in python when I had a error in code even while the code looked very perfect to me but latter when I changed assignment style all of sudden the code started working. The code looked some what like this before.
x=y=Queue()
x.put("a")
x.put("b")
print y.get()
later i changed to this and it started working
x=Queue()
y=Queue()
x.put("a")
x.put("b")
print y.get(10)
why do both code work differently?
Variables in Python are references, or names, not like variables in C etc.
This code:
x=y=Queue()
means "allow the name y to reference an object in memory made by calling Queue(), and allow the name x to reference the object that y is pointing to." This means both variables refer to the same object - as you can verify with id(x) == id(y).
This code:
x=Queue()
y=Queue()
means "allow the name x to reference one object made by Queue(), and allow the name y to reference another object made by Queue()". In this case, id(x) == id(y) is False
This can often bite you:
a = [1,2,3,4,5]
b = a
b.append(6)
print(a)
# [1,2,3,4,5,6] even though we didn't seem to do anything to a!
To get around this, do import copy; b = a.copy(); instead of b = a.
However, this behaviour doesn't occur to immutable objects like integers:
a = 7
a += 1
This doesn't go to the object that a is referencing and change it by adding one, instead it dereferences a from the object 7, and references it to the object representing the previous value of a + 1 (that is to say, 8). This is unlike actions performed on mutable objects, like lists in the previous example - appending to a list does change the object that the variable is referencing.
So we can do this:
a = 7
b = a
a += 1
print(a)
# 8
print(b)
# 7
Your first code is actually equivalent to:
y=Queue()
x=y
x.put("a")
x.put("b")
print y.get()
Which is different than your second example, because Python handles object by reference. After x=y both variables x and y refer to the same object. In your second example you have two independent queues.
Related
I've been learning Python for a few months, and also know very little C, and I was wondering if anyone could clear this doubt up for me:
Is a variable the name, the value, or the memory location?
For example:
x = 5
Is the variable x, the value of x, or the location of x in memory?
I'm looking for a clear explanation of what a variable is. I've already looked at Wikipedia's page on variables and this question, but neither were too clear to me. If this is a duplicate question, a link to the right answer would be great.
Thanks!
There are several things going on with the statement x=5:
an int object with the value of 5 is created (or found if it already exists);
the name x is created (or disassociated with the last object 'x' labeled);
the reference count to the new (or found) int object is increased by 1;
the name x is associated with the object with the value '5' created (or found).
Since int objects are immutable, they may be interned for efficiency. String objects are more likely to be interned.
Here are some examples:
>>> x=5 # discussed
>>> id(x) # the 'id' which in cPython is the memory address.
140246146681256
>>> y=x # now two names, 'x' and 'y' associated with that object
>>> id(y)
140246146681256 # same object
>>> z=5 # no guaranteed, likely the same object referred to by 'x' and 'y'
>>> id(z)
140246146681256 # id is the same! The object labeled 'x' was found and labeled 'z'
>>> del x # ref count to object '140246146681256' decreased by 1
>>> del y # same
>>> z
5
>>> id(z)
140246146681256 # same object but the names ''x' and 'y' no longer label it
The best way to think of variables names, like 'x' in x=5 is as a label.
It is possible to have objects with no label, such as the 5 individual string objects created in this list comprehension:
>>> li=[str(x) for x in range(5)]
>>> li
['0', '1', '2', '3', '4']
You can then create objects that match the value of those same 5 objects independently:
>>> li2=list('012345') # longer list; completely different construction
>>> li2
['0', '1', '2', '3', '4', '5']
You can get their individual memory addresses (in cPython) or a unique id address:
>>> [id(x) for x in li]
[4373138488, 4372558792, 4372696960, 4373139288, 4373139368]
>>> [id(x) for x in li2]
[4373138488, 4372558792, 4372696960, 4373139288, 4373139368, 4372696720]
Note that the two independently created lists of anonymous object are the same (for the first 5 in this case). I purposely used strings because they are more likely to be interred...
So think of it this way: two different processes are happening with x=5:
the object is created (or found if it is immutable, interned and exists) and
the object is labeled.
There is a space somewhere in a memory where the values are stored. These memory is then located through address which is usually represented by hexadecimal number, or sometimes binary number. So, these numbers are hard to remember for programmer, so they used the term variable to refer to that memory location in a easy way, or you can say higher abstraction. So, x is just a name that refers to some location in the memory which contains value of 5. That's all!
A variable is a mapping of a name to associated storage and serves as a way to refer to that storage location in your program. When you assign to a variable and perform operations on it, you're populating and altering that storage. When you reassign a variable, you can point it to a different storage location -- you are remapping that name.
In Python variables are best considered as names.
In the case of numbers, numbers are immutable so reassigning a variable will always make the variable point to a different number without changing the number.
x = 1
y = x
x += 1 # y is still 1
The difference is clearer with mutable objects, where you can change a value OR make the variable refer to a different value
x = [1,2,3]
y = x
x.append(4) # I mutated x's value, so y is now [1,2,3,4]
x = [] # I made x point to a different list, so y is still [1,2,3,4]
Recommended reading:
http://web.archive.org/web/20180411011411/http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html
http://me.veekun.com/blog/2012/05/23/python-faq-passing/
First Of All
The formal definition of "Memory Model" is a description of the behavior of multi-threaded data access, see Memory_model.
Data Model
According to your description, what you want to express is actually "Data Model", see Python Data Model.
Let me try to summarize:
In Python, data was represented by object.
Every object has three key concepts: identity, a type and a value.
identity: value never changed to identify an object, use id() function to check the id of an object. In CPython, id is object's memory address.
type: object's type, like int/ string/ list or so. never changed. type() to check.
value: the object's value. For example, for a string object, the value is "some string", and it is immutable.
Variable is just a symbol to refer to the object.
Your Question
what happens when typing: x=5?
an object with type int, value 5 was created(or reused if there already has).
a variable named x refer to the object. The object's reference counter increase 1.
That's all.
I assumed sequence types in Python were value types. It turns out they're reference types (Meaning that the value of a variable won't be copied when assigned to a new variable, but referenced). So now I'm wondering, what are the value types in Python? That is, what types in Python can I assign to new variables without worrying that the variable was referenced?
All values in Python are references. What you need to worry about is if a type is mutable. The basic numeric and string types, as well as tuple and frozenset are immutable; names that are bound to an object of one of those types can only be rebound, not mutated.
>>> t = 1, 2, 3
>>> t[1] = 42
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
Coming from iOS development using strongly typed Swift language, Python reference was a bit confusing so I decided to do a little comparison. Here is the summary: -
When assigning a variable to python say a = 10 you are simply pointing/referencing the the object in this case 10 which is stored in a memory. So if that object changes then the value of a variable a also changes but changing a does not change the object 10, This behave similar to Swift Primitive value types such as Int.
To make this clear here is an example: -
# "a" points to an object in this case 10
a = 10
# "b" points to the same object which a points but does not point to a variable a.
b = a
# Now if we change "a" to point to another object in memory say 20.
a = 20
# "b" still points to the old object 10 in other words
# "b == 10" but "a == 20", This is because "b" was never pointing to the variable "a"
# even though we assigned it as "b = a" instead it was pointing to the object 10
# which is # the same as writing b = 10.
Let's check with a more complex data structure List
list1 = [10,20,30,40]
list2 = list1 #[10,20,30,40]
list1 = [3,4]
# list1 ==> [3,4]
# list2 ==> [10,20,30,40]
Again that behave the same to Swift and other similar languages. Here comes the huge difference Let's try changing value at a certain index ( This gets more tricky)
list1 = [10,20,30,40]
list2 = list1 #[10,20,30,40]
# change value of list 1 at a certain index say index 0
list1[0] = 500
# If you check again the values of list1 and list2 you will be surprised.
#list1 ==> [500,20,30,40]
#list2 ==> [500,20,30,40]
They both change because they were all pointing to the same object so changing the object changes all list1 and list2. This is very confusing from other Languages such as Swift. In Swift List/Array are value types meaning they are not referenced instead they are copied around, However in python it is another story, changing a value at a certain index results in changing that value for all properties which references that object just like in the example above. This is very important to keep in mind for folks coming from Swift or other similar languages.
So how do we copy in python?
If you want to copy the list in python then you have to explicitly do so as shown on the example below: -
list1 = [10,20,30,40]
list2 = list(list1)
# list1 ==> [10,20,30,40]
# list2 ==> [10,20,30,40]
Doing so will avoid undesired effects when list1 changes list2 will remain the same.
As an example
list1[0] = 500
#list1 ==> [500,20,30,40] # Changed
#list2 ==> [10,20,30,40] # Unchanged
The answer above is correct, but I object to the semantics of "reference".
C-like languages treat variables as fixed buckets, in which values are placed. When you call a function, a new set of buckets are created, and the values are copied into them. Sometimes, a bucket is pass-by-reference, and actually becomes an alias for the caller's bucket.
Python, on the other hand, treats variables as mere labels (names) for values (objects). When you call a function, a new set of labels are created and slapped onto those same objects.
It doesn't make sense to mention "references" in the context of Python, because in every other language, "reference" implies an alternative to "value". Python has no such duality; it just passes around and assigns objects. Nothing is referred to.
Nitpicky, perhaps, but the terminology causes no end of confusion for C++ programmers, who e.g. hear Python passes by references and don't understand how to reassign the caller's names.
I assumed sequence types in Python were value types. It turns out they're reference types (Meaning that the value of a variable won't be copied when assigned to a new variable, but referenced). So now I'm wondering, what are the value types in Python? That is, what types in Python can I assign to new variables without worrying that the variable was referenced?
All values in Python are references. What you need to worry about is if a type is mutable. The basic numeric and string types, as well as tuple and frozenset are immutable; names that are bound to an object of one of those types can only be rebound, not mutated.
>>> t = 1, 2, 3
>>> t[1] = 42
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
Coming from iOS development using strongly typed Swift language, Python reference was a bit confusing so I decided to do a little comparison. Here is the summary: -
When assigning a variable to python say a = 10 you are simply pointing/referencing the the object in this case 10 which is stored in a memory. So if that object changes then the value of a variable a also changes but changing a does not change the object 10, This behave similar to Swift Primitive value types such as Int.
To make this clear here is an example: -
# "a" points to an object in this case 10
a = 10
# "b" points to the same object which a points but does not point to a variable a.
b = a
# Now if we change "a" to point to another object in memory say 20.
a = 20
# "b" still points to the old object 10 in other words
# "b == 10" but "a == 20", This is because "b" was never pointing to the variable "a"
# even though we assigned it as "b = a" instead it was pointing to the object 10
# which is # the same as writing b = 10.
Let's check with a more complex data structure List
list1 = [10,20,30,40]
list2 = list1 #[10,20,30,40]
list1 = [3,4]
# list1 ==> [3,4]
# list2 ==> [10,20,30,40]
Again that behave the same to Swift and other similar languages. Here comes the huge difference Let's try changing value at a certain index ( This gets more tricky)
list1 = [10,20,30,40]
list2 = list1 #[10,20,30,40]
# change value of list 1 at a certain index say index 0
list1[0] = 500
# If you check again the values of list1 and list2 you will be surprised.
#list1 ==> [500,20,30,40]
#list2 ==> [500,20,30,40]
They both change because they were all pointing to the same object so changing the object changes all list1 and list2. This is very confusing from other Languages such as Swift. In Swift List/Array are value types meaning they are not referenced instead they are copied around, However in python it is another story, changing a value at a certain index results in changing that value for all properties which references that object just like in the example above. This is very important to keep in mind for folks coming from Swift or other similar languages.
So how do we copy in python?
If you want to copy the list in python then you have to explicitly do so as shown on the example below: -
list1 = [10,20,30,40]
list2 = list(list1)
# list1 ==> [10,20,30,40]
# list2 ==> [10,20,30,40]
Doing so will avoid undesired effects when list1 changes list2 will remain the same.
As an example
list1[0] = 500
#list1 ==> [500,20,30,40] # Changed
#list2 ==> [10,20,30,40] # Unchanged
The answer above is correct, but I object to the semantics of "reference".
C-like languages treat variables as fixed buckets, in which values are placed. When you call a function, a new set of buckets are created, and the values are copied into them. Sometimes, a bucket is pass-by-reference, and actually becomes an alias for the caller's bucket.
Python, on the other hand, treats variables as mere labels (names) for values (objects). When you call a function, a new set of labels are created and slapped onto those same objects.
It doesn't make sense to mention "references" in the context of Python, because in every other language, "reference" implies an alternative to "value". Python has no such duality; it just passes around and assigns objects. Nothing is referred to.
Nitpicky, perhaps, but the terminology causes no end of confusion for C++ programmers, who e.g. hear Python passes by references and don't understand how to reassign the caller's names.
I'm trying to accomplish something with Python but I can't find info about this at all on internet so here is my problem.
Having this sample code:
a = 5
b = [a]
I need b[0] to be a pointer reference to a. Currently if I do
b[0] = 7
a.var will still be 5, and if I set value to a b[0], a keeps the same.
I'd like to know if there is any way in Python to store an Object in an array without copying this, so if I modify one I also modify another.
EDIT ONE
I want to clarify a bit better what I'm trying to accomplish so maybe I can find the real answer.
I have a custom class like
class Foo(object):
def __init__(self):
self.var = 7
I have also a list like this:
myList = [Foo()]
My real problem is here:
In some place of a code, I need to do the following assignment:
self.foo = myList[0]
Then when I try to access this foo var, I notice this is never updated from the original instance. So basically that is what I need.
Edit Two
All answers were right. Using id(var) on every step of my assignments I could verify the Object was the same all the time, so the error must be somewhere else. Thanks to everyone for all the help and I hope this post can help someone else in a future.
You already are storing the object, namely the integer 5. What you are not storing is the name-value binding between the name a and the value 5. Your problem is that the operation b[0] = 7 does not modify the object 5; it only modifies the binding between b[0] and its value (from 5 to 7), leaving the values themselves (5 and 7) untouched. In fact, you cannot modify the value 5, since 5 is an integer, and integers in Python are immutable.
Another way to say that is that b[0] = 7 does not modify the object referred to by b[0]; instead, it modifies the object referred to by b. b is a list, and lists are objects that internally keep track of what objects their indices point to. When you do b[0] = 7, this tells b "make your 0 index point at this new object". It does not "notify" 5 (the old value) or 7 (the new value) that they are now pointed to by b[0]. Objects in Python do not know what kinds of references point at them; they only know what they point at (if anything).
What you are asking for is not a way to store an object, but to store a "variable" --- that is, a binding between a name in the local namespace and a value. The answer is that there isn't, in general, a way to do this in Python. There's no construct that will allow you do b = something(a) so that when you later do b[0] = 8, a will change.
If you want to be able to modify the name-value binding, you need to change a, by making it some kind of object whose contents can be changed, instead of just making it a plain variable. For instance, if you do:
a = [5]
b = a
b[0] = 7
Then you will find a has also changed. The same will be true for other kinds of objects as well: if you set a to some other kind of object whose properties can be altered, and then you alter its properties in-place, those changes will show up no matter how you reference the object.
You may find it helpful to read up on how Python variables work, for instance in this article and this one.
Whether you can do this comes down to whether your list elements are immutable or mutable types. Immutable types can't be changed, so when you re-assign a variable that is immutable it's actually creating a new object and labeling it with the same label. Mutable types can be changed, so it's possible to change the underlying object without reassigning it.
For example, say that a is a list, which is a mutable type.
a = [5]
b = [a]
a[0] = 3
print(b)
# [[3]]
a.append('hi')
print(b)
# [[3, 'hi']]
Your test code actually works the way you want it, because objects are mutable.
class Object():
pass
a = Object()
a.var = 5
b = [a]
b[0].var = 7
print(a.var)
# 7
Your other example code should still work, for all the same reasons. When I assign a = l[0], it isn't copying anything, it's just creating an additional reference a to the object that l[0] references.
l = [Object() for _ in range(5)]
l[0].var = 5
a = l[0]
l[0].var = 7
print(a.var)
# 7
You write
a = 5
b = [a]
I need b[0] to be a pointer reference to a.
You can't. You can make a point to a mutable object and change the value for that object:
class Object(object):
'''an object'''
a = Object()
a.value = 5
b = a
b.value = 7
and now a.value returns:
7
Similarly, but with a list this time:
a = [5]
b = a
b[0] = 7
and now a[0] is:
7
I've been learning python and i've got a doubt and i'm not sure if what i'm thinking is the correct. As you know Python is an OOP Language and all objects have an id, type and a value.
However there's a concept that i'm not sure if i understood well. It's the mutable and immutable objects.
I know there are some objects that are mutables like arrays, lists and there are others that are immutable like strings, ints, tuples etc.
Basically the main diference is that the immutable can't change its value. For example if i've got an int var:
x = 1
its value is always the same.
After that line of code if i create another var x but now = 2, it's another object, because they have different id's, right? But now, how can i access a var by id, for example my first x var?
Hope you can help.
Thanks! :)
But now, how can i access a var by id, for example my first x var?
You can't. When you do:
x = 1
x = 2
when python executes the x = 2 the 1 object you assigned to x doesn't have any references that can reach it and thus you cannot access it in any way. There's no such a thing as get_object_from_id that allows you to reach any object given its id.
When an object doesn't have any reference to it, it is effectively unreachable. When the garbage collector will be run the object will be destroyed (actually, in CPython most of the objects are destroyed immediately, but there isn't any guarantee about when an object will be destroyed).
As Martijn pointed out, the id of an object is just an implementation detail and it may be reused by the interpreter when an object is destroyed, hence, even from a theoretical point of view, a function such as get_object_from_id can't be implemented in any sensible manner.
Also, assignments have nothing to do with mutable vs immutable types.
You can see the difference between mutable and immutable types when you perform operations on them. For example:
some_list.append(1)
Adds 1 to some_list (modifying it), without creating a new list object, while:
a = 1
a += 2
Here a is not modified by increasing its value to 3, but a new integer object of value 3 is assigned to a.
You can use the id to check that the as are different objects:
>>> a = 1
>>> id(a)
25889896
>>> a += 2
>>> id(a)
25889848
Note that relying on id is a really poor choice. For example:
>>> a = (1, 2)
>>> b = (1, 2)
>>> a is b # is compare the ids just like: id(a) == id(b)
False
>>> a[0] is b[0]
True
As you can see the interpreter decided to re-use the same object 1 for two different tuples. This is an optimization used for small integers, that works because integers are immutable.
Bottom line: id can only tell you if two things aren't the same thing at a certain moment in time. Any other use is just wrong.
This seems like more of a question about scope,.. for which I would recommend reading this.
http://docs.python.org/release/1.5.1p1/tut/scopes.html
say we have the following
x = 1
def PrintStuff(x):
print (x)
PrintStuff(2)
>>> 2
In the function PrintStuff, x is a local variable.
Outside the function PrintStuff lies a global variable x
To get the global x, there are multiple options, but for right now lets just use the globals() function, which returns a dictionary containing all global variables.
x = 1
def PrintStuff(x):
print( x)
print( globals()["x"])
PrintStuff(2)
>>> 2
>>> 1
Similarly we could use the locals() function to get the local x
def PrintStuff(x):
print( locals()["x"])
PrintStuff(2)
>>> 2