英文:
How to return a anonymous NamedTuple in python defined only in the return type hint
问题
I come from Typescript, new to Python. When I have 2 things to return from a function and I only use these 2 keys for that function return type and nowhere else in the code, I don't create a complete class but I instead use typescript convinient syntax:
fn(): {
'return_key_1': number,
'return_key_2': string,
} {
// statements..
return {
{
'return_key_1': 5,
'return_key_2': 'hello',
'error_key': 9, // IDE shows an error here as I didn't declared this key
}
}
which enables to create rapidly return data structure without the boilerplate of declaring an entire class, and I have all the IDE autocomplete and errors/warning associated with that data-structure.
Is there the same in Python? I saw there are NamedTuple, or new @dataclass classes from Python 3.7, but how do you make Python return a NamedTuple with defined keys without declaring the class elsewhere but in the return type?
I tried:
def fn(self) -> NamedTuple('MyTuple', fields=[('params', str), ('cursor_end', int)]):
return {
'params': 'hello',
'cursor_end': 4,
}
But PyCharm says "Expected type 'MyTuple', got 'dict[str, str | int]' instead"
英文:
I come from Typescript, new to Python. When I have 2 things to return from a function and I only use these 2 keys for that function return type and nowhere else in the code, I don't create a complete class but I instead use typescript convinient syntax:
fn(): {
'return_key_1': number,
'return_key_2': string,
} {
// statements..
return {
{
'return_key_1': 5,
'return_key_2': 'hello',
'error_key': 9, // IDE shows an error here as I didn't declared this key
}
}
which enables to create rapidly return data structure without the boilerplate of declaring a entire class, and I have all the IDE autocomplete and errors/warning associated to that data-structure.
Is there the same in Python ? I saw there are NamedTuple, or new @dataclass classes from Python 3.7, but how do you make Python return a NamedTuple with defined keys without declaring the class elsewhere but in the return type ?
I tried:
def fn(self) -> NamedTuple('MyTuple', fields = [('params', str), ('cursor_end', int)]):
return {
'params': 'hello',
'cursor_end': 4,
}
But PyCharm says "Expected type 'MyTuple', got 'dict[str, str | int]' instead"
答案1
得分: 2
由于您的样本函数返回一个字典,您应该使用typing.TypedDict
来指定返回值的类型:
from typing import TypedDict
def f() -> TypedDict('', {
'return_key_1': int,
'return_key_2': str,
}):
return {
'return_key_1': 5,
'return_key_2': 'hello',
'error_key': 9, # PyCharm shows an error here
}
请注意,正如@juanpa.arrivillaga在评论中指出的,虽然上述代码在PyCharm中看起来很干净且方便,但不幸的是,它并不是Python类型注释系统的官方部分。为了符合官方规范并满足严格遵循规范的工具,您需要预先定义TypedDict
,而不是内联定义,如下例所示,几乎与上面的代码相同,只是提前命名了TypedDict
:
from typing import TypedDict
MyDict = TypedDict('MyDict', {
'return_key_1': int,
'return_key_2': str,
})
def f() -> MyDict:
return {
'return_key_1': 'a',
'return_key_2': 'hello',
'error_key': 9,
}
在mypy中演示:https://mypy-play.net/?mypy=latest&python=3.11&gist=4fbb933f9f9441fced1931d7b32d4c7d
英文:
Since your sample function returns a dict, you should type the returning value with typing.TypedDict
instead:
from typing import TypedDict
def f() -> TypedDict('', {
'return_key_1': int,
'return_key_2': str,
}):
return {
'return_key_1': 5,
'return_key_2': 'hello',
'error_key': 9, # PyCharm shows an error here
}
Note, as @juanpa.arrivillaga points out in the comment, that while the above looks clean and conveniently works in PyCharm, it is unfortunately not officially part of the Python type annotation system. You would have to define the TypedDict
in advance instead of inline in order to conform to the official specifications and satisfy tools that strictly adhere to the specs, like the example below, which is almost identical to the code above except in naming the TypedDict
in advance:
from typing import TypedDict
MyDict = TypedDict('MyDict', {
'return_key_1': int,
'return_key_2': str,
})
def f() -> MyDict:
return {
'return_key_1': 'a',
'return_key_2': 'hello',
'error_key': 9,
}
Demo in mypy: https://mypy-play.net/?mypy=latest&python=3.11&gist=4fbb933f9f9441fced1931d7b32d4c7d
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论