1

I've found this statement in one of the answers to this question.

What does it mean? I would have no problem if the statement were "Python never implicitly copies dictionary objects". I believe tuples, lists, sets etc are considered "object" in python but the problem with dictionary as described in the question doesn't arise with them.

Ahmed Abdullah
  • 305
  • 2
  • 11
  • The answer states `x = y` never creates a copy of `y`. Anything mutable will be affected, lists and sets for instance. – Andras Deak -- Слава Україні May 04 '18 at 04:40
  • Yes, the statement is accurate. When doing an assignment, Python never implicitly assigns a copy of the right-hand side to the left. You must do this explicitly. – Christian Dean May 04 '18 at 04:41
  • 2
    Yes, it is accurate, assignment **never** copies, and works *exactly* the same for `list`, `set`, `tuple`, and `dict` objects (and all other objects). The difference between mutable types and immutable types is that *you cannot mutate immutable types*, therefore, you won't see a practical difference. But using the `id` function, you'll see that the behavior is the same. Also, this is important, **everything** in Python is an object.\ – juanpa.arrivillaga May 04 '18 at 04:42
  • 1
    read this: https://nedbatchelder.com/text/names.html – juanpa.arrivillaga May 04 '18 at 04:42
  • @juanpa.arrivillaga Or just use `is`. Probably easier. – Christian Dean May 04 '18 at 04:43
  • 2
    Actually, not only do lists have this problem, but novices seem to get bitten far more often with lists than with any other type. Dicts and numpy arrays are probably tied for a distant 2nd place. Notice that [the official Python FAQ question](https://docs.python.org/3/faq/programming.html#why-did-changing-list-y-also-change-list-x) and [our canonical question](https://stackoverflow.com/questions/2612802/) are both all about lists, and barely mention dicts as another example of a mutable type. – abarnert May 04 '18 at 05:07
  • @juanpa.arrivillaga Thanks again. confusion arose because i was checking this in different way. L1=[1,2,3] ; L2=L1; L1.append(4); print(L1) # [1,2,3,4]; print(L2) #[1,2,3,4]; Fine so far. But if L1=[1,2,3]; L2=L1 ; L1=[1,2,3,4]; print(L1) # [1,2,3,4]; print(L2) #[1,2,3]; Why this discrepancy? – Ahmed Abdullah May 04 '18 at 05:58
  • Again, read this: nedbatchelder.com/text/names.html – juanpa.arrivillaga May 04 '18 at 08:07

2 Answers2

5

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.

user2357112
  • 260,549
  • 28
  • 431
  • 505
  • 1
    You could also point out that `+=` and friends can "make an implicit copy" (e.g., `tup += ()`). Of course what's actually happening is the `__iadd__` or `__add__` method making a copy, followed by assignment not making a copy—but people coming from C++ are sometimes mislead by this behavior. – abarnert May 04 '18 at 05:10
  • Technically, in most (all?) cases but local variables, Python hands off the responsibility of assignment to a `__setitem__`, `__setattr__`, `__set__`, or `set_contents` method on some object. So it's not really that Python never copies, but that dict, list, slots-wrapper, property, and cell don't copy, and neither do any method inherited from `object`; beyond that, it's entirely up to whatever methods you (or a third-party, or even the stdlib, a la multiprocessing) want to do in those methods. (I don't think that would clarify things for most people even if you explained it better than me…) – abarnert May 04 '18 at 05:17
-1

python has a lot of difficult types. they are divide on two groups:
1) not change - integer, string, tuple
2) change - list, dictionary
for example:
- not change

x = 10

for this 'x' python create new object like 'Int' with link in memory 0x0001f0a

x += 1 # x = x + 1

python create new link in memory like 0x1003c00 - change

x = [1, 2, 'spam']

for this 'x' python create new object like 'Int' with link in memory 0x0001f0a

y = x

python copy link from 'x' to 'y'