Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
4.8k views
in Technique[技术] by (71.8m points)

python - Initialize a TypedDict and fill keys & values later

I have a dict with of which the types of the keys and values are fixed. I want to define the types in a TypedDict as follows:

class MyTable(TypedDict):
    caption: List[str]
    header: List[str]
    table: pd.DataFrame
    epilogue: List[str]

I have function that returns a MyTable. I want to define first an empty (Typed)dict and fill in keys and values.

def returnsMyTable():
    result = {}
    result['caption'] = ['caption line 1','caption line 2']
    result['header'] = ['header line 1','header line 2']
    result['table'] = pd.DataFrame()
    result['epilogue'] = ['epilogue line 1','epilogue line 2']
    return result

Here MyPy complains that a type annotation for result is needed. I tried the this:

result: MyTable = {}

but then MyPy complains that the keys are missing. Similarly, if I define the keys but set the values to None, it complains about incorrect types of the values.

Is it at all possible to initialize a TypedDict as an empty Dict first and fill in the keys and values later? The docs seem to suggest it is.

I guess I could first define the values as variables and assemble the MyTable later but I'm dealing with legacy code that I'm adding type hinting to. So I'd like to minimize the work.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

What you might want here is to set totality, but I'd think twice about using it.

Quoting the PEP

By default, all keys must be present in a TypedDict. It is possible to override this by specifying totality. Here is how to do this using the class-based syntax:

class MyTable(TypedDict, total=False):
    caption: List[str]
    header: List[str]
    table: pd.DataFrame
    epilogue: List[str]

result: MyTable = {}
result2: MyTable = {"caption": ["One", "Two", "Three"]}

As I said, think twice about that. A total TypedDict gives you a very nice guarantee that all of the items will exist. That is, because MyPy won't allow result to exist without "caption", you can safely call cap = result["caption"].

If you set total=False, that guarantee goes away. On the assumption that you're using your MyTable much more commonly than you're making it, getting the additional safety assurances when you use it is probably a good trade.

Personally, I'd reserve total=False for cases where the creation code sometimes genuinely does leave things out and any code that uses it has to handle that. If it's just a case of taking a few lines to initialise, I'd do it like this:

def returnsMyTable():
    result = {}
    result_caption = ['caption line 1','caption line 2']
    result_header = ['header line 1','header line 2']
    result_table = pd.DataFrame()
    result_epilogue = ['epilogue line 1','epilogue line 2']
    result = {
        "caption": result_caption, 
        "header": result_header, 
        "table": result_table, 
        "epilogue": result_epilogue
    }
    return result

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...