如何键入具有不同类型值的字典提示
How to type hint a dictionary with values of different types
将字典声明为文字时,有没有一种方法可以类型提示我期望特定键值是什么?
然后,讨论一下:在 Python 中是否有关于字典输入的指导原则?我想知道在字典中混合类型是否被认为是不好的做法。
这是一个例子:
考虑字典在 class 的 __init__
中的声明:
(免责声明:我意识到在示例中,某些 .elements
条目可能更适合作为 class 属性,但这是为了示例。 )
class Rectangle:
def __init__(self, corners: Tuple[Tuple[float, float]], **kwargs):
self.x, self.z = corners[0][0], corners[0][1]
self.elements = {
'front': Line(corners[0], corners[1]),
'left': Line(corners[0], corners[2]),
'right': Line(corners[1], corners[3]),
'rear': Line(corners[3], corners[2]),
'cog': calc_cog(corners),
'area': calc_area(corners),
'pins': None
}
class Line:
def __init__(self, p1: Tuple[float, float], p2: Tuple[float, float]):
self.p1, self.p2 = p1, p2
self.vertical = p1[0] == p2[0]
self.horizontal = p1[1] == p2[1]
当我输入以下内容时,
rec1 = Rectangle(rec1_corners, show=True, name='Nr1')
rec1.sides['f...
Pycharm 会为我建议 'front'
。更好的是,当我这样做时
rec1.sides['front'].ver...
Pycharm 会提示 .vertical
因此 Pycharm 记住了 class 的 __init__
中字典文字声明中的键,以及它们值的预期类型。或者更确切地说:它期望任何值都具有文字声明中的任何一种类型——可能就像我做了一个 self.elements = {} # type: Union[type1, type2]
一样。无论哪种方式,我都觉得它非常有用。
如果您的函数的输出带有类型提示,那么 Pycharm 也会将其考虑在内。
所以假设在上面的 Rectangle
示例中,我想指出 pins
是 Pin
个对象的列表...如果 pins
是一个正常的class 属性,则为:
self.pins = None # type: List[Pin]
(假设已完成必要的导入)
有没有办法在字典文字声明中给出相同类型的提示?
以下内容没有实现我正在寻找的东西:
在文字声明的末尾添加 Union[...]
类型提示?
'area': calc_area(corners),
'pins': None
} # type: Union[Line, Tuple[float, float], float, List[Pin]]
为每一行添加类型提示:
'area': calc_area(corners), # type: float
'pins': None # type: List[Pin]
}
这种事情有最佳实践吗?
更多背景:
我在 PyCharm 中与 Python 一起工作,我广泛使用打字,因为它可以帮助我预测和验证我的工作。当我创建新的 classes 时,我有时也会将一些不常用的属性放入字典中,以避免使用太多属性使对象混乱(这在调试模式下很有帮助)。
经过更多调查,目前我能找到的最佳解决方法是确保 class Pin
可以 return 某种占位符,然后使用占位符作为文字声明中的值。
因此:
class Pin:
def __init__(self, **kwargs):
if len(kwargs) == 0:
return
现在,在 OP 的示例中,我可以执行以下操作来实现我想要的:
...
'area': calc_area(corners),
'pins': List[Pin(),]
}
但是,如果我有一个(或多个)基本类型作为条目,这将不起作用。
...
'area': calc_area(corners),
'pins': List[Pin(),]
'color': None
'lap_times': None
}
在哪里
color
需要一个字符串并且
lap_times
需要一个带有浮点数的列表...
在这种情况下,最好的解决方法是
...
'area': calc_area(corners),
'pins': List[Pin(),]
'color': 'blue'
'lap_times': [0.,]
}
self.elements['color'], self.elements['lap_times'] = None, None
这两个看起来都不是很优雅,所以我仍然希望有人能提出更好的建议。
您正在寻找近期的 TypedDict. It is currently only a mypy-only extension, but there are plans to make it an officially sanctioned type。不过,我不确定 PyCharm 是否支持此功能。
所以,在你的情况下,你会这样做:
from mypy_extensions import TypedDict
RectangleElements = TypedDict('RectangleElements', {
'front': Line,
'left': Line,
'right': Line,
'rear': Line,
'cog': float,
'area': float,
'pins': Optional[List[Pin]]
})
class Rectangle:
def __init__(self, corners: Tuple[Tuple[float, float]], **kwargs):
self.x, self.z = corners[0][0], corners[0][1]
self.elements = {
'front': Line(corners[0], corners[1]),
'left': Line(corners[0], corners[2]),
'right': Line(corners[1], corners[3]),
'rear': Line(corners[3], corners[2]),
'cog': calc_cog(corners),
'area': calc_area(corners),
'pins': None
} # type: RectangleElements
如果您使用的是 Python 3.6+,您可以使用 class-based syntax.
更优雅地键入所有内容
但在您的具体情况下,我认为大多数人只会将这些数据片段存储为常规字段而不是字典。不过,我相信您已经仔细考虑了这种方法的优缺点,所以我将跳过对您的讲解。
将字典声明为文字时,有没有一种方法可以类型提示我期望特定键值是什么?
然后,讨论一下:在 Python 中是否有关于字典输入的指导原则?我想知道在字典中混合类型是否被认为是不好的做法。
这是一个例子:
考虑字典在 class 的 __init__
中的声明:
(免责声明:我意识到在示例中,某些 .elements
条目可能更适合作为 class 属性,但这是为了示例。 )
class Rectangle:
def __init__(self, corners: Tuple[Tuple[float, float]], **kwargs):
self.x, self.z = corners[0][0], corners[0][1]
self.elements = {
'front': Line(corners[0], corners[1]),
'left': Line(corners[0], corners[2]),
'right': Line(corners[1], corners[3]),
'rear': Line(corners[3], corners[2]),
'cog': calc_cog(corners),
'area': calc_area(corners),
'pins': None
}
class Line:
def __init__(self, p1: Tuple[float, float], p2: Tuple[float, float]):
self.p1, self.p2 = p1, p2
self.vertical = p1[0] == p2[0]
self.horizontal = p1[1] == p2[1]
当我输入以下内容时,
rec1 = Rectangle(rec1_corners, show=True, name='Nr1')
rec1.sides['f...
Pycharm 会为我建议 'front'
。更好的是,当我这样做时
rec1.sides['front'].ver...
Pycharm 会提示 .vertical
因此 Pycharm 记住了 class 的 __init__
中字典文字声明中的键,以及它们值的预期类型。或者更确切地说:它期望任何值都具有文字声明中的任何一种类型——可能就像我做了一个 self.elements = {} # type: Union[type1, type2]
一样。无论哪种方式,我都觉得它非常有用。
如果您的函数的输出带有类型提示,那么 Pycharm 也会将其考虑在内。
所以假设在上面的 Rectangle
示例中,我想指出 pins
是 Pin
个对象的列表...如果 pins
是一个正常的class 属性,则为:
self.pins = None # type: List[Pin]
(假设已完成必要的导入)
有没有办法在字典文字声明中给出相同类型的提示?
以下内容没有实现我正在寻找的东西:
在文字声明的末尾添加 Union[...]
类型提示?
'area': calc_area(corners),
'pins': None
} # type: Union[Line, Tuple[float, float], float, List[Pin]]
为每一行添加类型提示:
'area': calc_area(corners), # type: float
'pins': None # type: List[Pin]
}
这种事情有最佳实践吗?
更多背景:
我在 PyCharm 中与 Python 一起工作,我广泛使用打字,因为它可以帮助我预测和验证我的工作。当我创建新的 classes 时,我有时也会将一些不常用的属性放入字典中,以避免使用太多属性使对象混乱(这在调试模式下很有帮助)。
经过更多调查,目前我能找到的最佳解决方法是确保 class Pin
可以 return 某种占位符,然后使用占位符作为文字声明中的值。
因此:
class Pin:
def __init__(self, **kwargs):
if len(kwargs) == 0:
return
现在,在 OP 的示例中,我可以执行以下操作来实现我想要的:
...
'area': calc_area(corners),
'pins': List[Pin(),]
}
但是,如果我有一个(或多个)基本类型作为条目,这将不起作用。
...
'area': calc_area(corners),
'pins': List[Pin(),]
'color': None
'lap_times': None
}
在哪里
color
需要一个字符串并且
lap_times
需要一个带有浮点数的列表...
在这种情况下,最好的解决方法是
...
'area': calc_area(corners),
'pins': List[Pin(),]
'color': 'blue'
'lap_times': [0.,]
}
self.elements['color'], self.elements['lap_times'] = None, None
这两个看起来都不是很优雅,所以我仍然希望有人能提出更好的建议。
您正在寻找近期的 TypedDict. It is currently only a mypy-only extension, but there are plans to make it an officially sanctioned type。不过,我不确定 PyCharm 是否支持此功能。
所以,在你的情况下,你会这样做:
from mypy_extensions import TypedDict
RectangleElements = TypedDict('RectangleElements', {
'front': Line,
'left': Line,
'right': Line,
'rear': Line,
'cog': float,
'area': float,
'pins': Optional[List[Pin]]
})
class Rectangle:
def __init__(self, corners: Tuple[Tuple[float, float]], **kwargs):
self.x, self.z = corners[0][0], corners[0][1]
self.elements = {
'front': Line(corners[0], corners[1]),
'left': Line(corners[0], corners[2]),
'right': Line(corners[1], corners[3]),
'rear': Line(corners[3], corners[2]),
'cog': calc_cog(corners),
'area': calc_area(corners),
'pins': None
} # type: RectangleElements
如果您使用的是 Python 3.6+,您可以使用 class-based syntax.
更优雅地键入所有内容但在您的具体情况下,我认为大多数人只会将这些数据片段存储为常规字段而不是字典。不过,我相信您已经仔细考虑了这种方法的优缺点,所以我将跳过对您的讲解。