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.
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'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
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.
This question already has answers here:
How do I pass a variable by reference?
(39 answers)
Closed 9 months ago.
My code :
locs = [ [1], [2] ]
for loc in locs:
loc = []
print locs
# prints => [ [1], [2] ]
Why is loc not reference of elements of locs ?
Python : Everything is passed as reference unless explicitly copied [ Is this not True ? ]
Please explain.. how does python decides referencing and copying ?
Update :
How to do ?
def compute(ob):
if isinstance(ob,list): return process_list(ob)
if isinstance(ob,dict): return process_dict(ob)
for loc in locs:
loc = compute(loc) # What to change here to make loc a reference of actual locs iteration ?
locs must contain the final processed response !
I don't want to use enumerate, is it possible without it ?
Effbot (aka Fredrik Lundh) has described Python's variable passing style as call-by-object: http://effbot.org/zone/call-by-object.htm
Objects are allocated on the heap and pointers to them can be passed around anywhere.
When you make an assignment such as x = 1000, a dictionary entry is created that maps the string "x" in the current namespace to a pointer to the integer object containing one thousand.
When you update "x" with x = 2000, a new integer object is created and the dictionary is updated to point at the new object. The old one thousand object is unchanged (and may or may not be alive depending on whether anything else refers to the object).
When you do a new assignment such as y = x, a new dictionary entry "y" is created that points to the same object as the entry for "x".
Objects like strings and integers are immutable. This simply means that there are no methods that can change the object after it has been created. For example, once the integer object one-thousand is created, it will never change. Math is done by creating new integer objects.
Objects like lists are mutable. This means that the contents of the object can be changed by anything pointing to the object. For example, x = []; y = x; x.append(10); print y will print [10]. The empty list was created. Both "x" and "y" point to the same list. The append method mutates (updates) the list object (like adding a record to a database) and the result is visible to both "x" and "y" (just as a database update would be visible to every connection to that database).
Hope that clarifies the issue for you.
Everything in Python is passed and assigned by value, in the same way that everything is passed and assigned by value in Java. Every value in Python is a reference (pointer) to an object. Objects cannot be values. Assignment always copies the value (which is a pointer); two such pointers can thus point to the same object. Objects are never copied unless you're doing something explicit to copy them.
For your case, every iteration of the loop assigns an element of the list into the variable loc. You then assign something else to the variable loc. All these values are pointers; you're assigning pointers; but you do not affect any objects in any way.
It doesn't help in Python to think in terms of references or values. Neither is correct.
In Python, variables are just names. In your for loop, loc is just a name that points to the current element in the list. Doing loc = [] simply rebinds the name loc to a different list, leaving the original version alone.
But since in your example, each element is a list, you could actually mutate that element, and that would be reflected in the original list:
for loc in locs:
loc[0] = loc[0] * 2
When you say
loc = []
you are rebinding the loc variable to a newly created empty list
Perhaps you want
loc[:] = []
Which assigns a slice (which happens to be the whole list) of loc to the empty list
Everything is passed by object. Rebinding and mutating are different operations.
locs = [ [1], [2] ]
for loc in locs:
del loc[:]
print locs
Why is loc not reference of elements of locs ?
It is. Or at least, it is in the same sense that every other variable in Python is. Python variables are names, not storage. loc is a name that is used to refer to elements of [[1,2], [3,4]], while locs is a name that refers to the entire structure.
loc = []
This does not mean "look at the thing that loc names, and cause it to turn into []". It cannot mean that, because Python objects are not capable of such a thing.
Instead, it means "cause loc to stop being a name for the thing that it's currently a name for, and start instead being a name for []". (Of course, it means the specific [] that's provided there, since in general there may be several objects in memory that are the same.)
Naturally, the contents of locs are unchanged as a result.