Skip to content

Non-primitive type (object) defaults are shared between instances #154

Closed
@atleta

Description

Hi,

If you use any non-primitive type as a default and create a model so that the default is used (i.e. not specifying the field in the serialized data) then you will end up having the same instance across all the instances (that were initized with the default). Now, in hindshight it's not surprising, because this is what happens when you have such a default for a function parameter, but the documentation is misleading as it contains an example suggesting you could do this:

class User(BaseModel):
    id: int
    name = 'John Doe'
    signup_ts: datetime = None
    friends: List[int] = []

While if now you create two users:

u1, u2 = [User(id=i) for i in range(2)]

You'll have u1.friends is u2.friends. This one is easy to step aside by always providing a friends list, but in my case I wanted to use a defaultdict, which, it seems can be fixed with validators (using always=True, and also copying the values from the dict created by pydantic) but it would be nice to be able to use factory functions for a more declarative style. E.g. if you know FactoryBoy, something like that. (Though, probably one should still have a converting validator if there is actually data for that field.)

But at least the documentation should be fixed.

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions