In the code:
y = 7
x = y
x = 8
Now, y will be 7 and x will be 8. But actually I wan to change y. Can I assign the reference of y and do that?
For example, in C++ the same thing can be achieved as:
int y = 8;
int &x = y;
x = 9;
Now both y & x will be 9
No, you cannot. As other answer point out, you can (ab?)use aliasing of mutable objects to achieve a similar effect. However, that's not the same thing as C++ references, and I want to explain what actually happens to avoid any misconceptions.
You see, in C++ (and other languages), a variable (and object fields, and entries in collections, etc.) is a storage location and you write a value (for instance, an integer, an object, or a pointer) to that location. In this model, references are an alias for a storage location (of any kind) - when you assign to a non-reference variable, you copy a value (even if it's just a pointer, it's still a value) to the storage location; when you assign to a reference, you copy to a storage location somewhere else. Note that you cannot change a reference itself - once it is bound (and it has to as soon as you create one) all assignments to it alter not the reference but whatever is referred to.
In Python (and other languages), a variable (and object fields, and entries in collections, etc.) is a just a name. Values are somewhere else (e.g. sprinkled all over the heap), and a variable refers (not in the sense of C++ references, more like a pointer minus the pointer arithmetic) to a value. Multiple names can refer to the same value (which is generally a good thing). Python (and other languages) calls whatever is needed to refer to a value a reference, despite being pretty unrelated to things like C++ references and pass-by-reference. Assigning to a variable (or object field, or ...) simply makes it refer to another value. The whole model of storage locations does not apply to Python, the programmer never handles storage locations for values. All he stores and shuffles around are Python references, and those are not values in Python, so they cannot be target of other Python references.
All of this is independent of mutability of the value - it's the same for ints and lists, for instance. You cannot take a variable that refers to either, and overwrite the object it points to. You can only tell the object to modify parts of itself - say, change some reference it contains.
Is this a more restrictive model? Perhaps, but it's powerful enough most of the time. And when it isn't you can work around it, either with a custom class like the one given below, or (equivalent, but less obvious) a single-element collection.
class Reference:
def __init__(self, val):
self._value = val # just refers to val, no copy
def get(self):
return self._value
def set(self, val):
self._value = val
That still won't allow you to alias a "regular" variable or object field, but you can have multiple variables referring to the same Reference object (ditto for the mutable-singleton-collection alternative). You just have to be careful to always use .get()/.set() (or [0]).
No, Python doesn't have this feature.
If you had a list (or any other mutable object) you could do what you want by mutating the object that both x and y are bound to:
>>> x = [7]
>>> y = x
>>> y[0] = 8
>>> print x
[8]
See it working online: ideone
Alternatively, you could use a self crafted container.
class Value(object):
def __init__(self, value): self.value = value
y = Value(7)
x = y
x.value = 8
print y.value
ideone
You should use a mutable object for this.
In python x & y are just references to objects
so y = 7 means y points to the object 7.
x=y means x too points to 7, but as 7 is immutable so changing the value of x simply changes the object 7 and y still remains pointing to 7.
>>> y = [7]
>>> x = y
>>> x[0] = 8 # here you're changing [7] not x or y, x & y are just references to [7]
>>> y
[8]
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'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
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.
I am trying to figure out whether the following are immutable in Sage (which is built on Python so I believe if it is immutable in python, I believe in most cases it will be immutable in Sage)
Below are objects e, f, g, i
class e: pass
f = e()
g = pi # (g's "type" in Sage is symbolic expression. It's supposed to be 3.1415....etc)
i = lambda x: x*x
I gather that e is a class which means it is mutable (Does an immutable class make sense? Can't all classes be modified?). Since f is an instance of a class, I am guessing it is also mutable since classes are mutable.
Since numbers are immutable in Python, g should be immutable as well since it is a number despite being irrational
Finally i is a function which means it should be mutable?
I'm not quite sure I understand that concept of immutability. What would it mean for a function to be immutable? For a class to be immutable?
e is mutable. You can, for instance, add a new method on the class: e.foo = lambda self,x: x.
f is mutable. You can, for instance, add a new field to this class instance: f.x = 99.
g is immutable. You can't change anything about it.
i is not immutable. You can do all sorts of evil things to it: i.func_code = (lambda x: 123).func_code after which i(10) will be 123 instead of 100. (You can also do more reasonable things to it. After i.__doc__ = "This function returns the square of its argument." you will get a more helpful result from help(i).)
An object is mutable if there's something you can do to the object that changes its possible future behaviour. You can't change the behaviour of 10; you can change the behaviour of a function object, or a class, or a class instance, or a list. (But not a tuple. Once a tuple is made, it stays just as it is for as long as it exists.)
Formally? An object is mutable if it can change value without changing identity.
Lists are mutable, so the value of a particular instance can change over time:
>>> x = orig_x = []
>>> x == []
True
>>> x += [1]
>>> x == [] # The value of x has changed
False
>>> x is orig_x # But the identity remains the same
True
Numbers are immutable, however, so their value can't change. Instead, the variable has to be updated to refer to a completely different object:
>>> x = orig_x = 1
>>> x == 1
True
>>> x += 1
>>> x == 1 # Again, the value of x has changed
False
>>> x is orig_x # But now the identity has changed as well
False
Immutability is an important concept, since knowing that an object's value can't change lets you make certain assumptions about it (for example, dict effectively requires immutable keys and set and frozenset require immutable members, as the value of an object affects how it should be stored in the data structure. If mutable entries were permitted, they may end up being in the wrong place if they are modified after being stored)
Contrary to popular belief, user defined classes that don't override the definition of equality are technically immutable. This is because the default definition of the "value" of a user defined class is just id(self). When an object's value is its identity, there is obviously no way for them to differ over time, and hence the object doesn't quality as "mutable".
Informally? Most people use an intuitive "Can I change it?" definition along the lines of Gareth McCaughan's answer. It's the same basic idea as the formal definition, just using a broader meaning of the term "value" than the technical definition in terms of equality checks.