Reputation: 544
I'll try to clarify:
For example, I make a function that locally creates a list, and return it. How does Python create the returned list that exist outside the function body ? Does it use "deepcopy" (or something similar) ?
In [50]: def create_list():
...: sublist1 = [1,2,3]
...: sublist2 = [4,5,6]
...: list_of_lists=[sublist1,sublist1,sublist2]
...: return list_of_lists
...:
In [51]: l=create_list()
In [52]: l
Out[52]: [[1, 2, 3], [1, 2, 3], [4, 5, 6]]
In [53]: l[0].append(4)
In [54]: l
Out[54]: [[1, 2, 3, 4], [1, 2, 3, 4], [4, 5, 6]]
Here, the returned list l
still contains the sublists. And l[0]
and l[1]
still reference the same sublist (which is normal Python behavior). So the list and its structure were copied.
And if I call once again create_list()
:
In [55]: l2=create_list()
In [56]: l2
Out[56]: [[1, 2, 3], [1, 2, 3], [4, 5, 6]]
In [57]: l
Out[57]: [[1, 2, 3, 4], [1, 2, 3, 4], [4, 5, 6]]
A new list l2
has been created, but l
is unaffected, which means it does exist outside the function, and its sublists are its own, not references to sublists that would still exist in the function body.
So my question : does Python used deepcopy or something similar to make l
?
Not matter what kind of object I return with a function, it will be unaffected by subsequent call to this function ?
(as long as the object was created locally in the function)
Do not hesitate to tell me if I'm not clear enough. Thanks,
Upvotes: 7
Views: 10909
Reputation: 1185
This might not directly answer this question but should help clarify related concept.
If you create a nested object inside a function and return it, the object will continue to exist. It would not go out of scope even though the function ended.
Example Code
class Some_Class (object):
prop_x = None
def __init__(self, prop_x ):
self.prop_x = prop_x
def __repr__(self):
return "prop_x = "+repr (self.prop_x)
def fx ():
dict_x = { "k1" : "v1" }
print hex ( id (dict_x) )
obj1 = Some_Class ( prop_x = dict_x )
print hex ( id (obj1.prop_x) )
print "obj1 is "+repr( obj1 )
return obj1
recv_obj = fx ()
print "recv_obj is "+repr( recv_obj )
print hex ( id (recv_obj.prop_x) )
Output
0xdfaae0
0xdfaae0
obj1 is prop_x = {'k1': 'v1'}
recv_obj is prop_x = {'k1': 'v1'}
0xdfaae0
A dict, dict_x
, is assigned to prop_x
variable of a Class object obj1
. The dict is not created again in memory but a soft copy
takes place. prop_x
points to the memory location of dict_x
.
When you return object obj1
at the end of this function, dict_x
goes out of scope but the memory address used by it, 0xdfaae0
, is still pointed by prop_x
in the returned object recv_obj
. So, the dict values { "k1" : "v1" }
are preserved in memory.
Upvotes: 4
Reputation: 1779
Variables in Python are pointers to objects. So a function would return a pointer to an object created in the function, obviating the need for copying return values.
Upvotes: 0
Reputation: 97601
When you run the function the second time, the entire function is rerun - it has no memory along the lines of "last time, sublist1
was [1, 2, 3]
".
You haven't copied the list [1, 2, 3]
. You've created it twice.
Note that if you use a caching decorator like @functools.lru_cache
, you'll get surprising results:
>>> @lru_cache()
... def create_list():
... sublist1 = [1,2,3]
... sublist2 = [4,5,6]
... list_of_lists=[sublist1,sublist1,sublist2]
... return list_of_lists
...
>>> l = create_list(); l
[[1, 2, 3], [1, 2, 3], [4, 5, 6]]
>>> l[0].append(4); l
[[1, 2, 3, 4], [1, 2, 3, 4], [4, 5, 6]]
>>> create_list()
[[1, 2, 3, 4], [1, 2, 3, 4], [4, 5, 6]]
Because in this case, python does have a memory of the previous result, and returns the same object
Upvotes: 3