Skip to content

BaseModel.copy produces copy that modifies the original #1383

@physicsrob

Description

@physicsrob

Bug

When copying a model, changing the value of an attribute on the copy updates the value of the attribute on the original. This only happens if deep != True. If this is expected behavior, I would suggest the documentation needs to be updated, because it's different than the intuition one would have for shallow copies of standard python objects.

My expectation of a shallow copy: Modifying a mutable attribute on the child SHOULD modify the mutable attribute on the parent (the attribute should be the same object). Setting the value of an attribute on the child, however, SHOULD NOT set the value on the original.

Output of python -c "import pydantic.utils; print(pydantic.utils.version_info())":

             pydantic version: 1.4
            pydantic compiled: True
                 install path: /Users/rob/opt/anaconda3/envs/words_ml/lib/python3.8/site-packages/pydantic
               python version: 3.8.2 (default, Mar 25 2020, 11:22:43)  [Clang 4.0.1 (tags/RELEASE_401/final)]
                     platform: macOS-10.15.4-x86_64-i386-64bit
     optional deps. installed: []

Reproduction:

from pydantic import BaseModel
from typing import Optional, List

class X(BaseModel):
    val: int

x = X(val=1)

y = x.copy()
y.val= 2

print(f"{x.val =}") # x.val =2
print(f"{y.val =}") # y.val =2 -- setting the value on the copy also set the value on the original?


# My expectation would be that the behavior would be similar to standard python objects:
x = {'val': 1}
y = x.copy()
y['val'] = 2
print(f"{x['val'] =}") # x.val =1
print(f"{y['val'] =}") # y.val =2

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions