【问题标题】:pydantic BaseModel with instance variable带有实例变量的 pydantic BaseModel
【发布时间】:2021-05-27 10:52:04
【问题描述】:

我正在使用 pydantic 和 fastapi。 而且,我是这样制作模型的。

# model.py

from multiprocessing import RLock
from pydantic import BaseModel

class ModelA(BaseModel):
    file_1: str = 'test'

    def __init__(self, **data: Any):
        super().__init__(**data)
        self._lock = RLock()
        self._instance_variable: int = 1

    @property
    def lock(self):
        return self._lock

    @property
    def instance_variable(self) -> int:
        with self.lock:
            return self._instance_variable

    @instance_variable.setter
    def instance_variable(self, v: int) -> int:
        assert isinstance(v, int)
        with self.lock:
            self._instance_variable = v

我做这样的测试

# test_model_a.py

def test_model_a():
    instance = ModelA()
    assert instance.json() == '{"field_1": "test"}'

之后,我运行测试,但无法创建实例并出现此错误。

E ValueError: "ModelA" object has no field "_lock"

那么,我怎样才能通过这个测试...? 请...帮帮我...

【问题讨论】:

  • 你不应该用字符串比较来做你的断言;实际上 JSON 的缩进可能会有所不同(例如空格)。我建议改用 BaseModel.dict() 并比较 2 个对象。
  • 对于我的问题,您的回答并不重要。我的问题是“propery.setter”不起作用

标签: python python-3.x python-typing pydantic


【解决方案1】:

您需要使用PrivateAttr 字段。而不是二传手,使用__setattr__的解决方法

from multiprocessing import RLock, synchronize
from typing import Any

from pydantic import BaseModel, PrivateAttr


class ModelA(BaseModel):
    file_1: str = 'test'
    _lock: synchronize.RLock = PrivateAttr()
    _instance_variable: int = PrivateAttr()

    def __init__(self, **data: Any):
        super().__init__(**data)
        self._lock = RLock()
        self._instance_variable: int = 1

    @property
    def lock(self):
        return self._lock

    @property
    def instance_variable(self) -> int:
        with self.lock:
            return self._instance_variable

    def __setattr__(self, key, val):
        if key == "instance_variable":
            assert isinstance(val, int)
            with self.lock:
                self._instance_variable = val
            return
        super().__setattr__(key, val)

您也可以避免使用自定义__init__


class ModelA(BaseModel):
    file_1: str = 'test'
    _lock: synchronize.RLock = PrivateAttr(default_factory=RLock)
    _instance_variable: int = PrivateAttr(1)
# ...

【讨论】:

猜你喜欢
  • 2020-09-12
  • 1970-01-01
  • 1970-01-01
  • 2022-10-07
  • 1970-01-01
  • 1970-01-01
  • 2022-06-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多