Does Python make a copy of objects on assignment?
This is because in Python, variables (names) are just references to individual objects. When you assign dict_a = dict_b
, you are really copying a memory address (or pointer, if you will) from dict_b
to dict_a
. There is still one instance of that dictionary.
To get the desired behavior, use either the dict.copy
method, or use copy.deepcopy
if your dict may have nested dicts or other nested objects.
>>> a = {1:2}
>>> b = a.copy()
>>> b
{1: 2}
>>> b[3] = 4
>>> a
{1: 2}
>>> b
{1: 2, 3: 4}
>>>
Does python copy objects on assignment?
It doesn't copy anything. It's just that assigning to self.curstack
does not modify whatever self.curstack
used to refer to. It just makes self.curstack
refer to something else.
Think of it this way. self.curstack
points to some stuff. With objs = self.curstack
you make objs
point to that same stuff. With self.curstack = []
, you make self.curstack
point to an empty list. This doesn't remove any of the stuff that self.curstack
used to point at; that stuff is still there and objs
is still pointing at it.
This article explains it using a nice analogy of label tags.
Does Python copy objects on instance attribute assignment?
Does Python make a copy of objects on assignment?
This is because in Python, variables (names) are just references to individual objects. When you assign dict_a = dict_b, you are really copying a memory address (or pointer, if you will) from dict_b to dict_a. There is still one instance of that dictionary.
In your example, df
and instance.df
is the same thing of dict_a
and dict_b
, which is only holding the reference of the instance.
How to delete every reference of an object in Python?
No no no. Python has a garbage collector that has very strong territory issues - it won't mess with you creating objects, you don't mess with it deleting objects.
Simply put, it can't be done, and for a good reason.
This is by design and intentional, delete the variable of df, would not eliminate the existence of the instance, it only remove the reference from you df, therefore, as long as instance.df
is still holding the instance, you could still access it even you deleted the variable df
.
Is copy.copy different from assignment in python
All python variables are bindings to some objects in memory.
- Does this code do anything?
Yes, it does.
Actually it creates a new object in memory with new name.
- How does
copy.copy(node
) differ fromnode = node
?
By assignment you are getting different names for the same object.
So if you are really need a copy
you should use shallow
or deep
copy.
Example:
>>> x = [1]
>>> id(x)
35964488
>>> y = x
>>> id(y)
35964488
>>> z = x[:]
>>> id(z)
35964768
So x
and y
have same id
, while z
has different.
Same here:
>>> import copy
>>> c = copy.copy(x)
>>> id(c)
35985168
>>> id(x)
35964488
Quote from docs about shallow
and deep
copy:
The difference between shallow and deep copying is only relevant for
compound objects (objects that contain other objects, like lists or
class instances):A shallow copy constructs a new compound object and then (to the extent possible) inserts references into it to the objects found in
the original.A deep copy constructs a new compound object and then, recursively, inserts copies into it of the objects found in the
original.
Shouldn't shallow copy create an object with different id in python?
In python, assignment never copies data. You just get a new name that references the same value.
There are basically three cases:
Assignment: just a new name that points to the same object.
copy.copy
the object itself is copied, but members of the object are not. So a shallow copy of a list will be a new list, have a new ID but will point to the same objects in memory for its elements as the original list.
copy.deepcopy
recursively copies everything.
Good resources:
http://www.pythontutor.com/visualize.html#mode=edit
Ned Batchelder, Facts and myths about python names and vague https://youtu.be/_AEJHKGk9ns
Is it true that Python never implicitly copies objects ?
The statement in the linked answer is broader than it should be. Implicit copies are rare in Python, and in the cases where they happen, it is arguable whether Python is performing the implicit copy, but they happen.
What is definitely true is that the default rules of name assignment do not involve a copy. By default,
a = b
will not copy the object being assigned to a
. This default can be overridden by a custom local namespace object, which can happen when using exec
or a metaclass with a __prepare__
method, but doing so is extremely rare.
As for cases where implicit copies do happen, the first that comes to mind is that the multiprocessing
standard library module performs implicit copies all over the place, which is one of the reasons that multiprocessing
causes a lot of confusion. Assignments other than name assignment may also involve copies; a.b = c
, a[b] = c
, and a[b:c] = d
may all involve copies, depending on what a
is. a[b:c] = d
is particularly likely to involve copying d
's data, although it will usually not involve producing an object that is a copy of d
.
python: changes to my copy variable affect the original variable
That is because in python setting a variable actually sets a reference to the variable. Almost every person learning python encounters this at some point. The solution is simply to copy the list:
copy_list = org_list[:]
Is Copying for List Assignments acceptable?
There is nothing inherently wrong with this. As long as your class is well documented, if you have a good reason to do this go for it. Consider the following class from the standard library shelve
module, which essentially provides a dict-like database interface. Since using object[key] = value
will write to disk, and retrieving that object will retrieve it from disk, it won't give you the same object (necessarily, there are caching options)! So:
In [1]: import shelve
In [2]: data = [[1,2,3],[4,5,6]]
In [3]: database = shelve.open('db')
In [4]: database['key'] = data[0]
In [5]: database['key']
Out[5]: [1, 2, 3]
In [6]: database['key'] is data[0]
Out[6]: False
That part of the documentation is referring to assignment statements to a variable, like this:
some_var = foo
Where indeed, it never copies. And you can't really change that (well, maybe, but that's another question). You are free to implement __setitem__
and __getitem__
however you wish.
How do I clone a list so that it doesn't change unexpectedly after assignment?
new_list = my_list
doesn't actually create a second list. The assignment just copies the reference to the list, not the actual list, so both new_list
and my_list
refer to the same list after the assignment.
To actually copy the list, you have several options:
You can use the builtin
list.copy()
method (available since Python 3.3):new_list = old_list.copy()
You can slice it:
new_list = old_list[:]
Alex Martelli's opinion (at least back in 2007) about this is, that it is a weird syntax and it does not make sense to use it ever. ;) (In his opinion, the next one is more readable).
You can use the built in
list()
constructor:new_list = list(old_list)
You can use generic
copy.copy()
:import copy
new_list = copy.copy(old_list)This is a little slower than
list()
because it has to find out the datatype ofold_list
first.If you need to copy the elements of the list as well, use generic
copy.deepcopy()
:import copy
new_list = copy.deepcopy(old_list)Obviously the slowest and most memory-needing method, but sometimes unavoidable. This operates recursively; it will handle any number of levels of nested lists (or other containers).
Example:
import copy
class Foo(object):
def __init__(self, val):
self.val = val
def __repr__(self):
return f'Foo({self.val!r})'
foo = Foo(1)
a = ['foo', foo]
b = a.copy()
c = a[:]
d = list(a)
e = copy.copy(a)
f = copy.deepcopy(a)
# edit orignal list and instance
a.append('baz')
foo.val = 5
print(f'original: {a}\nlist.copy(): {b}\nslice: {c}\nlist(): {d}\ncopy: {e}\ndeepcopy: {f}')
Result:
original: ['foo', Foo(5), 'baz']
list.copy(): ['foo', Foo(5)]
slice: ['foo', Foo(5)]
list(): ['foo', Foo(5)]
copy: ['foo', Foo(5)]
deepcopy: ['foo', Foo(1)]
Related Topics
How to Filter Only Printable Characters in a File on Bash (Linux) or Python
Multi Platform Portable Python
Running a Bash Script from Python
Executable Python Program with All Dependencies for Linux
Checking Running Python Script Within the Python Script
I Have a Problem with Sending Mail:Typeerror: _Init_() Got an Unexpected Keyword Argument 'Context'
Use Df Command to Show Only the %Used
How to Run Celery Workers by Superuser
Change Parent Shell's Environment from a Subprocess
Creating a Symbolic in Shared Volume of Docker and Accessing It in Host MAChine
How to Install Writable Shared and User Specific Data Files with Setuptools
How Does Asyncio Actually Work
Differencebetween a String and a Byte String
How to Use Phantomjs in Python
Label Encoding Across Multiple Columns in Scikit-Learn
Importing a CSV File into a SQLite3 Database Table Using Python