OiO.lk Community platform!

Oio.lk is an excellent forum for developers, providing a wide range of resources, discussions, and support for those in the developer community. Join oio.lk today to connect with like-minded professionals, share insights, and stay updated on the latest trends and technologies in the development field.
  You need to log in or register to access the solved answers to this problem.
  • You have reached the maximum number of guest views allowed
  • Please register below to remove this limitation

How to type hint a dictionary with values of different types [duplicate]

  • Thread starter Thread starter levraininjaneer
  • Start date Start date
L

levraininjaneer

Guest
When declaring a dictionary as a literal, is there a way to type-hint what value I am expecting for a specific key?

And then, for discussion: are there guiding principles around dictionary typing in Python? I'm wondering whether it is considered bad practice to mix types in dictionaries.



Here's an example:

Consider the declaration of a dictionary in a class's __init__ :

(Disclaimer: I realize in the example, some of the .elements entries would probably be more appropriate as class attributes, but it's for the sake of the example.)

Code:
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]

When I type type the following,

Code:
rec1 = Rectangle(rec1_corners, show=True, name='Nr1')
rec1.sides['f...

Pycharm will suggest 'front' for me. Better still, when I do

Code:
rec1.sides['front'].ver...

Pycharm will suggest .vertical

So Pycharm remembers the keys from the dictionary literal declaration in the class's __init__, and also their values' expected types. Or rather: it expects any value to have any one of the types that are in the literal declaration - probably the same as if I had done a self.elements = {} # type: Union[type1, type2] would do. Either way, I find it super helpful.

If your functions have their outputs type-hinted, then Pycharm will also take that into account.

So assuming that in the Rectangle example above, I wanted to indicate that pins is a list of Pin objects... if pins was a normal class attribute, it would be:

Code:
    self.pins = None  # type: List[Pin]

(provided the necessary imports were done)

Is there a way to give the same type hint in the dictionary literal declaration?

The following does not achieve what I am looking for:

Add a Union[...] type hint at the end of the literal declaration?

Code:
            'area': calc_area(corners),
            'pins': None
        }  # type: Union[Line, Tuple[float, float], float, List[Pin]]

Adding a type-hint to every line:

Code:
            'area': calc_area(corners),  # type: float
            'pins': None  # type: List[Pin]
        }

Is there a best practice for this kind of thing?



Some more background:

I work with Python in PyCharm and I make extensive use of typing, since it helps me to predict and validate my work as I go along. When I create new classes, I also sometimes throw some less frequently used properties into a dictionary to avoid cluttering the object with too many attributes (this is helpful in debug mode).
<p>When declaring a dictionary as a literal, is there a way to type-hint what value I am expecting for a specific key?</p>
<p>And then, for discussion: are there guiding principles around dictionary typing in Python? I'm wondering whether it is considered bad practice to mix types in dictionaries.</p>
<hr />
<p>Here's an example:</p>
<p>Consider the declaration of a dictionary in a class's <code>__init__</code> :</p>
<p><em>(Disclaimer: I realize in the example, some of the <code>.elements</code> entries would probably be more appropriate as class attributes, but it's for the sake of the example.)</em></p>
<pre><code>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]
</code></pre>
<p>When I type type the following,</p>
<pre><code>rec1 = Rectangle(rec1_corners, show=True, name='Nr1')
rec1.sides['f...
</code></pre>
<p>Pycharm will suggest <code>'front'</code> for me. Better still, when I do</p>
<pre><code>rec1.sides['front'].ver...
</code></pre>
<p>Pycharm will suggest <code>.vertical</code></p>
<p>So Pycharm remembers the keys from the dictionary literal declaration in the class's <code>__init__</code>, and also their values' expected types. Or rather: it expects any value to have any one of the types that are in the literal declaration - probably the same as if I had done a <code>self.elements = {} # type: Union[type1, type2]</code> would do. Either way, I find it super helpful.</p>
<p>If your functions have their outputs type-hinted, then Pycharm will also take that into account.</p>
<p>So assuming that in the <code>Rectangle</code> example above, I wanted to indicate that <code>pins</code> is a list of <code>Pin</code> objects... if <code>pins</code> was a normal class attribute, it would be:</p>
<pre><code> self.pins = None # type: List[Pin]
</code></pre>
<p>(provided the necessary imports were done)</p>
<p>Is there a way to give the same type hint in the dictionary literal declaration?</p>
<p>The following does <strong>not</strong> achieve what I am looking for:</p>
<p>Add a <code>Union[...]</code> type hint at the end of the literal declaration?</p>
<pre><code> 'area': calc_area(corners),
'pins': None
} # type: Union[Line, Tuple[float, float], float, List[Pin]]
</code></pre>
<p>Adding a type-hint to every line:</p>
<pre><code> 'area': calc_area(corners), # type: float
'pins': None # type: List[Pin]
}
</code></pre>
<p>Is there a best practice for this kind of thing?</p>
<hr />
<p>Some more background:</p>
<p>I work with Python in PyCharm and I make extensive use of typing, since it helps me to predict and validate my work as I go along. When I create new classes, I also sometimes throw some less frequently used properties into a dictionary to avoid cluttering the object with too many attributes (this is helpful in debug mode).</p>
 

Latest posts

Top