在将字典声明为文字时,是否有一种方法可以提示我特定键的值?
然后进行讨论:是否有关于在python中键入字典的指导原则?我想知道在字典中混合类型是否被认为是不好的做法。
这是一个例子:
考虑在类的__init__
中声明字典:
(免责声明:我在示例中意识到,某些.elements
条目可能更适合作为类属性,但这只是为了示例)。
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会记住类__init__
中字典文字声明中的键以及它们的值的预期类型。或者更确切地说:它期望任何值都具有文字声明中的任何一种类型-可能与我完成self.elements = {} # type: Union[type1, type2]
时可以使用的类型相同。无论哪种方式,我都觉得它很有帮助。
如果您的函数具有类型提示的输出,则Pycharm也会将其考虑在内。
因此,假设在上面的Rectangle
示例中,我想表明pins
是Pin
对象的列表...如果pins
是普通的类属性,应该是
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,并且大量使用了输入,因为它可以帮助我在进行过程中预测和验证我的工作。当我创建新类时,有时还会将一些不常用的属性放入字典中,以避免过多的属性使对象混乱(这在调试模式下很有用)。
答案 0 :(得分:6)
您正在寻找TypedDict。目前,它只是一个仅适用于mypy的扩展程序,但是不久之后,就有计划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进行更优雅的键入。
不过,在您的特定情况下,我认为大多数人只会将这些数据存储为常规字段而不是字典。我确定您已经考虑了这种方法的优缺点,所以我将不为您讲解。
答案 1 :(得分:0)
经过更多调查,到目前为止,我能找到的最佳解决方法是确保类Pin
可以返回某种占位符,然后将占位符用作文字声明中的值。
因此:
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
这些都不是很优雅,所以我仍然希望有人可以提出更好的建议。