Specifying Argument Type For List of Dictionary For a Python Function
Asked Answered
R

2

20

I have a function whose argument is a list of dictionaries. I am trying to specify the type of elements for the dictionary in the function argument. The dictionary has the following form:

{'my_object':my_object, 'data':int}

my_object is a custom datatype. Is there any way to specify the type of dictionary, something like the one in below:

def my_function(x : list[dict[my_object, int]]):

Python complains about how I defined the type and gives me the following error:

TypeError: 'type' object is not subscriptable
Rahn answered 20/7, 2020 at 3:47 Comment(4)
typing.TypedDict might be what you're looking for?Repentance
The TypeError message is true: the list and dict classes is not subscriptable.You need to use List and Dict, after importing them from typing. However, neither is quite what you want; as @IainShelvington points out, you probably want typing.TypedDict (new in Python 3.8). I don't think you can state the type of your parameter x as accurately as you'd like in Py3.7 -- no type for dicts with heterogeneous values (or keys).Backfill
@AFPP Did you ever get a good resolution on this?Bobsleigh
Your use of dict assumes that all the keys are strings, and you are simply listing the value types, but you aren't indicating which key maps to which types. Positional order isn't appropriate: would your use case really consider {'data': int, "my_object": my_object} to have a different, incorrect type?Fecundate
P
23

You can try this:

from typing import List, Dict


def get_list_of_dicts(name: str, surname: str) -> List[Dict[str, str]]:
    return [{'name': name, 'surname': surname}]


print(get_list_of_dicts('Frank', 'Zappa'))

I hope it is useful for you.

Plasmagel answered 21/6, 2021 at 14:32 Comment(0)
B
-1

If you are asking can you specify a list of dictionaries containing a custom object as keys, then the answer is below. If you wish to specify more than one type of object as a key within the same dictionary though, this won't work.

You can do the former in Python 3.9 with type aliases. Reference https://docs.python.org/3/library/typing.html gives example with list of dicts.

Example below shows a list of dicts containing custom objects as keys.

from collections.abc import Sequence

class MyClass: 
    def __init__(self, arg1, arg2):
        self.attr1 = arg1 + arg2

class AnotherClass: 
    def __init__(self, arg1, arg2):
        self.attr1 = arg1 + arg2
    
seq1 = dict[MyClass, int]
seq2 = list[seq1]

def myfunc(arg1: Sequence[seq2]) -> seq2:
    for dict in arg1:
        for key, value in dict.items():
                print(key.attr1, value)

#Correct type provided.
myobj1 = MyClass('A', '1')
myobj2 = MyClass('B','2')
listdict= [{myobj1: 10, myobj2: 20}, {myobj2: 100, myobj1: 200}]
listdict
myfunc(listdict)

#Incorrect type provided.  
myobj1 = AnotherClass('A', '1')
myobj2 = AnotherClass('B','2')
listdict= [{myobj1: 10, myobj2: 20}, { myobj2: 100, myobj1: 200}]
myfunc(listdict)
        

A1 10
B2 20
B2 100
A1 200

Note: Linters may not recognize valid inputs though. E.g. mypy complains that the list of dict(object, int) is not a sequence thereof.

Bobsleigh answered 16/1, 2021 at 13:37 Comment(7)
This assumes that the keys of dict are all of type MyClass; the example in the question talks about a dict with string keys, but each key's value has a particular type.Fecundate
@Chepner, thank you for noticing that. Corrected as above.Bobsleigh
You didn't really fix anything. You are just pointing out that the OP's attempt is no longer a type error. It still doesn't do what the OP is actually asking about, even in Python 3.9.Fecundate
OP: 'my_object is a custom datatype. Is there any way to specify the type of dictionary, something like the one in below:' The issue is that he specifies it and gets a 'subscriptable' error. My answer shows that yes there is a way to specify it without getting the subscriptable error.Bobsleigh
"The dictionary has the following form: {'my_object':my_object, 'data':int} ". Their attempt is wrong whether or not dict supports index notation.Fecundate
I see your point that the OP in the first few lines seems to ask for a dictionary where specific keys of different types are specified. However further down they ask for something of the form def my_function(x : list[dict[my_object, int]]): To me [my_object, int] refers to keys equalling my_object and values being int. In which case the answer stands.Bobsleigh
That's what they tried, which is still wrong. You aren't answering the question they actually asked.Fecundate

© 2022 - 2024 — McMap. All rights reserved.