У меня есть два класса: Top и Nested , и для их создания мне нужно предоставить TopDefinition и NestedDefinition объекты, которые имеют тип NamedTuple (определения необходимы для аннотаций типов).И Class Top содержит атрибут, представляющий собой список вложенных объектов экземпляров.
Существует вложенный dict, который используется для создания экземпляра именованного кортежа.Формат ввода item
выглядит следующим образом:
type =<class 'dict'>
value={'t1': 'qwe', 't2': 'QWE', 't3': [{'n1': 'aaa', 'n2': 1}, {'n1': 'bb', 'n2': 3}]}
Затем он распаковывается для создания экземпляра класса TopDefinition с кодом
q = Top(top=TopDefinition(**item))
для использования.в качестве входных данных для создания экземпляра класса Top .и это хорошо работает, позже я вижу в типе класса q и значении входного параметра:
type=<class '__main__.TopDefinition'>
value=TopDefinition(t1='qwe', t2='QWE', t3=[{'n1': 'aaa', 'n2': 1}, {'n1': 'bb', 'n2': 3}])
, что экземпляр TopDefinition правильно создается как именованный кортеж с полями: t1, t2, t3.
Вопрос в том, что такое тип t3?
Это список dicts или список именованных кортежей (неявно преобразованный, потому что он определен в TopDefinition as List [NestedTuple] ?
Вывод предполагает, что это список dicts, потому что когда я перебираю t3, отображая тип и значение, я вижу:
type=<class 'dict'>,
value={'n1': 'aaa', 'n2': 1}
Is named_tuple=False
Затем я распаковываю {'n1': 'aaa', 'n2': 1}
с помощью **, чтобы создать NestedDefinition экземпляр, который работает нормально, так что это должен быть dict.
С другой стороны, mypy (с параметрами -ignore-missing-import --strict) говорит error: Argument after ** must be a mapping
, что означает для меня, что это не диктат.
Полный код для запуска ниже:
"""Replicate the problem."""
from typing import Any, List, NamedTuple
class NestedDefinition(NamedTuple):
"""Nested object metadata for mypy type annotation."""
n1: str
n2: int
class TopDefinition(NamedTuple):
"""Top object metadata for mypy type annotation."""
t1: str
t2: str
t3: List[NestedDefinition]
def isnamedtupleinstance(x: Any) -> bool:
"""Check if object is named tuple."""
t = type(x)
b = t.__bases__
print("-------{}".format(b))
if len(b) != 1 or b[0] != tuple:
return False
f = getattr(t, '_fields', None)
if not isinstance(f, tuple):
return False
return all(type(n) == str for n in f)
class Nested:
"""Nested object."""
n1: str
n2: int
def __init__(self, nested: NestedDefinition) -> None:
print("{cName} got:\n\ttype={y}\n\tvalue={v}\n\tIS named_tuple: {b}".format(
cName=type(self).__name__, y=type(nested), v=nested, b=isnamedtupleinstance(nested)))
self.n1 = nested.n1
self.n2 = nested.n2
class Top:
"""Top object."""
t1: str
t2: str
t3: List[Nested]
def __init__(self, top: TopDefinition) -> None:
print("{cName} got:\n\ttype={y}\n\tvalue={v}".format(cName=type(self).__name__,
y=type(top), v=top))
self.t1 = top.t1
self.t2 = top.t2
self.t3 = []
if top.t3:
for sub_item in top.t3:
print("Nested passing:\n\ttype={t},\n\tvalue={v}\n\tIs named_tuple={b}".format(
t=type(sub_item), v=sub_item, b=isnamedtupleinstance(sub_item)))
nested = Nested(nested=NestedDefinition(**sub_item))
self.addNestedObj(nested)
def addNestedObj(self, nested: Nested) -> None:
"""Append nested object to array in top object."""
self.t3.append(nested)
def build_data_structure(someDict: List) -> None:
"""Replicate problem."""
for item in someDict:
print("Top passing:\n\ttype ={type}\n\tvalue={value}".format(
type=type(item), value=item))
w = Top(top=TopDefinition(**item))
x = [
{
't1': 'qwe',
't2': 'QWE',
't3': [
{'n1': 'aaa', 'n2': 1},
{'n1': 'bb', 'n2': 3}
]
},
{
't1': 'asd',
't2': 'ASD',
't3': [
{'n1': 'cc', 'n2': 7},
{'n1': 'dd', 'n2': 9}
]
}
]
build_data_structure(someDict=x)