簡體   English   中英

如何從 position 而不是名稱給出的字段值初始化 Pydantic object?

[英]How to initialize a Pydantic object from field values given by position instead of name?

我無法找到如何從 position 給出的字段值(例如在列表而不是字典中)初始化 Pydantic object 的簡單方法,所以我編寫了 class 方法positional_fields()來從可迭代對象創建所需的字典:

from typing import Optional, Iterable, Any, Dict
from pydantic import BaseModel


class StaticRoute(BaseModel):
    if_name: str
    dest_ip: str
    mask: str
    gateway_ip: str
    distance: Optional[int]
    
    @classmethod
    def positional_fields(cls, values: Iterable) -> Dict[str, Any]:
        return dict(zip(cls.__fields__, values))


input_lines = """
  route ab 10.0.0.0 255.0.0.0 10.220.196.23 1
  route gh 10.0.2.61 255.255.255.255 10.220.198.38 1
""".splitlines()

for line in input_lines:
    words = line.split()
    if words and words[0] == 'route':
        sroute = StaticRoute(**StaticRoute.positional_fields(words[1:]))
        print(sroute)
if_name='ab' dest_ip='10.0.0.0' mask='255.0.0.0' gateway_ip='10.220.196.23' distance=1
if_name='gh' dest_ip='10.0.2.61' mask='255.255.255.255' gateway_ip='10.220.198.38' distance=1

有沒有更直接的方法來實現這一目標?

我的方法期望__fields__字典的鍵按照字段在 class 中定義的順序排列。我不確定這是否得到保證(假設 Python 3.6+)。

改用數據類怎么樣? 就像是:

from typing import Optional

from pydantic.dataclasses import dataclass


@dataclass
class StaticRoute:
    if_name: str
    dest_ip: str
    mask: str
    gateway_ip: str
    distance: Optional[int]


words = "route if_name dest_ip mask gateway_ip 10".split()
print(StaticRoute(*words[1:])

# StaticRoute(if_name='if_name', dest_ip='dest_ip', mask='mask', gateway_ip='gateway_ip', distance=10)

BaseModel類具有類方法parse_obj() ,它返回一個由字典初始化的對象實例。 類似的方法可以創建一個新方法parse_iterable() ,它返回一個由可迭代對象初始化的對象實例。

from typing import Optional, Iterable, Any, Dict
from pydantic import BaseModel


class BaseModelExt(BaseModel):
    @classmethod
    def parse_iterable(cls, values: Iterable) -> dict[str, Any]:
        return cls.parse_obj(dict(zip(cls.__fields__, values)))

    
class StaticRoute(BaseModelExt):
    if_name: str
    dest_ip: str
    mask: str
    gateway_ip: str
    distance: Optional[int]


input_lines = """
  route ab 10.0.0.0 255.0.0.0 10.220.196.23 1
  route gh 10.0.2.61 255.255.255.255 10.220.198.38 1
""".splitlines()

for line in input_lines:
    words = line.split()
    if words and words[0] == 'route':
        sroute = StaticRoute.parse_iterable(words[1:])
        print(sroute)

您可以使用自定義 RootTypeNamedTuple的組合,如下所示:

from pydantic import BaseModel
from typing import NamedTuple, Optional


class StaticRouteTuple(NamedTuple):
    if_name: str
    dest_ip: str
    mask: str
    gateway_ip: str
    distance: Optional[int]


class StaticRoute(BaseModel):
    __root__: StaticRouteTuple

    @property
    def route(self) -> StaticRouteTuple:
        return self.__root__


input_lines = """
  route ab 10.0.0.0 255.0.0.0 10.220.196.23 1
  route gh 10.0.2.61 255.255.255.255 10.220.198.38 1
""".splitlines()

for line in input_lines:
    words = line.split()
    if words and words[0] == "route":
        sroute = StaticRoute.parse_obj(words[1:]).route
        print(sroute)

如果您不想使用自定義 RootType,您可以改用pyandic.parse_obj_as ,例如:

from pydantic import parse_obj_as
sroute = parse_obj_as(StaticRouteTuple, words[1:])

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM