Pydantic: Correct use of @property setter for a field

Created on 28 May 2020  路  3Comments  路  Source: samuelcolvin/pydantic

Question

I don't know if this justifies the use of pydantic here's what I want to use pydantic for:

  1. Use a set of Fileds for internal use and expose them via @property decorators
  2. Set the value of the fields from the @property setters. But since the BaseModel has an implementation for __setattr__, using setters for a @property doesn't work for me.

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

pydantic version: 1.5.1
pydantic compiled: True
install path: /path/to/conda-env/lib/python3.7/site-packages/pydantic
python version: 3.7.6 | packaged by conda-forge | (default, Jan  7 2020, 22:33:48)  [GCC 7.3.0]
platform: Linux-5.0.0-32-generic-x86_64-with-debian-buster-sid
optional deps. installed: []
from pydantic import BaseModel

class DemoClassWithInternalFields(BaseModel):
    """Class with internal Fields"""
    field1_: str = 'DefaultValueForFieldOne'
    field2_: int = 0

    @property
    def field1(self):
        return self.field1_

    @property
    def field2(self):
        return self.field2_

    @field1.setter
    def field1(self, new_val):
        self.field1_ = new_val

    @field2.setter
    def field2(self, new_val):
        self.field2_ = new_val

    class Config:
        fields = {
            'field1_': 'field1',
            'field2_': 'field2'
        }
>>> obj1 = DemoClassWithInternalFields(field1='ConstructedValue', field2=10)
>>> obj1.field2 = 19  #Doesn't work

site-packages/pydantic/main.cpython-37m-x86_64-linux-gnu.so in pydantic.main.BaseModel.__setattr__()

ValueError: "DemoClassWithInternalFields" object has no field "field2"



md5-1df1ba5f0219ccdc4d2c9a523ff25688



```py
>>> obj2 = DemoClassWithPropertySetters(field1='ConstructedValue', field2=10)
>>> obj2.field2 = 11   # This works
>>> obj2.dict(by_alias=True)
{'field1': 'ConstructedValue', 'field2': 11}

Questions that stem from this are as follows:

  1. Is there a better workaround for this?
  2. What is the best way to expose and set values for a Field via @properties?
question

Most helpful comment

The solution might be computed fields https://github.com/samuelcolvin/pydantic/issues/935#issuecomment-555036039.
They're not that well explained, but I'm hoping to work on them soon.

All 3 comments

I don't see why you need properties and setters? why not just normal fields?

Yeah, you could use just fields there was some way of setting field value by aliases.
May be I am missing something but I wanted a way to perform field validation internally and use it as a class attribute.

This implementation is done here for example. The field masses_ (Snippet 1) is used via decorated @property like as shown in the second snippet. It would be nice to have this feature work for property setters as well.

https://github.com/MolSSI/QCElemental/blob/846928c80b686e88f2ffc9c3375195db0394f865/qcelemental/models/molecule.py#L147-L154

https://github.com/MolSSI/QCElemental/blob/846928c80b686e88f2ffc9c3375195db0394f865/qcelemental/models/molecule.py#L360-L365

The solution might be computed fields https://github.com/samuelcolvin/pydantic/issues/935#issuecomment-555036039.
They're not that well explained, but I'm hoping to work on them soon.

Was this page helpful?
0 / 5 - 0 ratings