Understanding python's memory model [duplicate] - python

This question already has answers here:
Is a variable the name, the value, or the memory location?
(5 answers)
Closed 9 years ago.
Consider the following log:
>>> y = 20000
>>> id(y)
36638928
>>> y = 1000000
>>> id(y)
36639264
As you can see, after changing the value of y, it's id changed as well.
Does it mean that int is immutable? what is happening behind the scenes?
Thanks!

Yes, integers are immutable. What you need to realize is that:
A variable is simply a name which you use to reference an object.
20000 and 1000000 are two unique integer objects. This means that they will never share the same memory address simultaneously.
In simple terms, when you execute this line:
y = 20000
two things happen:
An integer object 20000 is created in the object space.
A name y is created in the namespace and pointed to that object.
When you execute this one:
y = 1000000
two more things happen:
A new integer object 1000000 is created in the object space.
The name y is changed to point to that object instead of 20000.

Related

*= multiplier question between arrays and integers [duplicate]

This question already has answers here:
Why does += behave unexpectedly on lists?
(9 answers)
Closed 1 year ago.
I'm trying to learn coding through some tutorials and encountered something curious as I'm going over operators. The basic ones I get, but some others (like *= here) throw me off.
a = 1
b = a
a *= 2
print(a)
print(b)
Output
2
1
But when a is an array, this happens:
a = np.array([1, 2, 3, 3, 5, 5])
b = a
a *= 2
print(a)
print(b)
Output
[2 4 6 6 10 10]
[2 4 6 6 10 10]
Any insight as to why this happens? I can't really find much about it. The only thing I came across was "coercion rules"; does the second instance happen because a is being assigned to an array but then to an integer? Or is it a matter of the print statement order?
It's probably trivial but I'm just curious, thanks!
The Simple answer to your question is,
There are two kinds of objects in Python: Mutable objects and Immutable objects. The value of a mutable object can be modified in place after it’s creation, while the value of an immutable object cannot be changed.
Immutable(Not Modifiable) Object: int, float, long, complex, string tuple, bool
Mutable(Modifiable) Object: list, dict, set, byte array, user-defined classes.
So,here in your case firstly a and b are immutable objects as it belongs to class int in python,"b=a" means b is pointing towards a address,and as you update value of a to a*=2, the value is store on new memory location, but b is still pointing towards older address, thats why b is not showing changed value of a.
For more understanding of memory management in python, please read this blog, thankyou :)
https://medium.com/#tyastropheus/tricky-python-i-memory-management-for-mutable-immutable-objects-21507d1e5b95

are strings in python mutable, if not explain this? [duplicate]

This question already has answers here:
Aren't Python strings immutable? Then why does a + " " + b work?
(22 answers)
Closed 3 years ago.
I have declared a string "y as hello than tried to change character "h" by "m" using replace method in python and i checked for the type(y): its showing string
but when I googled, its showing strings are immutable... please explain
>>> y="hello"
>>> y=y.replace("h","m")
>>> y
'mello'
>>> type(y)
<class 'str'>
You didn't mutate the String, you changed what String y pointed to.
y originally pointed to "hello", then you ran the line y=y.replace("h","m") and caused y to instead point to the String "mello". The original String "hello" was never mutated, since Strings are indeed immutable.
Yes, strings are immutable. When you run the line
y=y.replace("h","m")
you are creating a new string, not changing the first one. The first string can't actually be changed.
String in Python are immutable (cannot change to allow for optimization of using one dictionary for all strings).
For example:
>>> y="hello"
>>> y.replace("h","m")
'mello'
>>> y
'hello'
When we want to change a string, we can either use bytearray or (often better) - just create a new string. Consider for example the method 'replace'. It did not change the string in the example - but we could assign it's return value.
>>> y1 = y.replace("h","m")
>>> y1
'mello'
Or even use the same variable y, in which case it will create a new string and overwrite the previous value of y.
>>> y = y.replace('h','m')
>>> y
'mello'
Which is just like putting a new value alltogether:
>>> y = 'a new value'
>>> y
a new value

Python 3 integer addresses [duplicate]

This question already has answers here:
The `is` operator behaves unexpectedly with non-cached integers
(2 answers)
Closed 1 year ago.
x=300
y=300
print(id(x),id(y))
a=[300,300]
print(id(a[0]),id(a[1]))
On executing above code I get different addresses for x and y but the same address for a[0] and a[1]. Can anyone tell me why that is happening?
Take a look at below example:
>>> a=256
>>> b=256
>>> print(id(a),id(b))
(31765012, 31765012)
>>>
>>> c=257
>>> d=257
>>> print(id(c),id(d))
(44492764, 44471284)
>>>
This will help you understand the unexpected behavior for integers. Whenever you create a int in range -5 to 256 you actually just get back a reference to the existing object. This is called Integer Caching in python.
In CPython, the C-API function that handles creating a new int object is PyLong_FromLong(long v). see the documentation on this link
EDIT: Now coming to the list. For the same list elements (larger integers) you are getting same id's because list is created at once or you can say in one go.
You can achieve similar behavior with integers as well, see below example with parallel assignment.
>>>
>>> a,b = 300,300
>>>
>>> print(id(a),id(b))
(36132288, 36132288)
>>>
Hope this will clear your doubts.

why did the value of "x" change? [duplicate]

This question already has answers here:
Changing one list unexpectedly changes another, too [duplicate]
(5 answers)
Changing an element in one list changes multiple lists [duplicate]
(4 answers)
How do I clone a list so that it doesn't change unexpectedly after assignment?
(24 answers)
How to deep copy a list?
(10 answers)
Closed 5 years ago.
Here is my code:
x = [[1],[1],[1],[-1]]
a = [[-2,-1,-1,-2],[1,-2,2,-1],[-1,-2,-2,-1],[2,-1,1,-2]]
h = 0.1
def K(h,a,x):
cont = [1,2,3,4]
k = []
for i in range(len(cont)):
k.append(h*cont[i])
y = x
print('original value',x)
for j in range(len(y)):
y[j][0] += k[j]/4
print('modified value',x)
K(h,a,x)
So the question is why did the value of x change if it has not received anything?
When you put:
y = x
All x is doing is acting as a pointer to the list object in memory. When you do the above, you are saying I want y to point to the same list that x references in the memory. Any changes in place changes to y will also affect x.
If you wish to have the reference y point to a different object in memory (with the same values as x,) you need to make a copy of x.
y = x[:] #make a copy. SEE EDIT
Now y and x will be pointing to different list objects in memory, but both objects will have the same values.
Note that any mutable datatype in python shares this reference property, such as: sets, dictionaries, lists, byte arrays and also some classes.
Look into the differences between mutable and immutable datatypes in python as this distinction is critical and will lead to undiagnosible bugs without knowledge on how python accesses different data types.
EDIT!!
Sorry, I did not notice x is made of a series of lists. You need to use deepcopy to copy the nested lists!
from copy import deepcopy
y = deepcopy(x)
When you write:
y = x
You're literally saying that x equals y. This doesn't make a copy of x. Whatever you do to x will happen to y and vice versa. You need to make a copy of x if you want them to be independent.

Are Python arguments passed by reference? [duplicate]

This question already has answers here:
How do I pass a variable by reference?
(39 answers)
Closed 7 years ago.
In detail, my question is this:
Given the following code,
x = 10
def func(x):
x = x+1
def main():
print(x)
func(x)
print(x)
if __name__ == '__main__':
main()
On running this I get:
10
10
Does this mean that Python does not pass values by reference?
And I did check through the other question of the sort, and most(if not all) included analogies of lists or other such examples.
Is it possible to explain this in simple terms, like just a simple integer?
Ps. I am a beginner to coding.
Thanks
If you are coming from a background such as C or C++, which I did, this can be maddening until you figure it out.
Python has names, not variables, and names are bound to objects. Effectively, you can think of all 'variables' or names, as being pointers to python objects.
In python, integers, floats, and strings are immutable. So when you do the following:
x = 10
x = x + 1
You are first binding the name x to the integer 10, then when you evaluate x + 1 you get a new object 11 and then you bind x to that object. Your x inside the function body is local to the function, and when you bind it to 11, the global x remains bound to 10.
If you were to pass a list to the function, and append something to the list, that list would be modified. A list in python is a mutable object. All names bound to the list would refer to the modified list.
As a result, when you pass mutable objects it may seem as if you are passing by reference, and when you pass immutable objects it may seem like you are passing by value.

Categories