我有两个类: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 类型是什么?
它是字典列表还是命名元组列表(隐式转换,因为它在TopDefinition中定义为List[NestedTuple]?
输出表明这是字典列表,因为当我遍历 t3 时,显示类型和价值,我看到:
type=<class 'dict'>,
value={'n1': 'aaa', 'n2': 1}
Is named_tuple=False
然后我{'n1': 'aaa', 'n2': 1}
用 ** 解包以创建工作正常的NestedDefinition实例,所以它应该是一个字典。
另一方面,mypy(带有选项--ignore-missing-imports --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)