[英]How to type-hint a getter to only allow keys of dict?
I wonder how to make this getter more type-safe:我想知道如何使这个 getter 更类型安全:
VALUES = {
'1': 'One',
'2': 'Two',
'3': 'Three'
}
def get(key : str) -> str:
return VALUES[key]
Instead of the type str
I would love to have a keyof VALUES
and type(VALUES[key])
types.我希望拥有一个
keyof VALUES
和type(VALUES[key])
类型,而不是str
类型。
get('4')
should throw a invalid type warning then as this key does not exist. get('4')
应该抛出一个无效类型警告,因为这个键不存在。 Not sure if this is possible with Python as I properly live in a TypeScript wonderland... :-)
不确定这是否可以用 Python 实现,因为我确实生活在 TypeScript 仙境中......
:-)
TypeScript would properly look like this: TypeScript 应该是这样的:
get<K extends keyof VALUES>(key : K): typeof K
{
return VALUES[key];
}
You cannot do this in general .一般情况下您不能这样做。 However, you can accomplish what you want in this particular case using
typing.Literal
:但是,在这种特殊情况下,您可以使用
typing.Literal
完成您想要的typing.Literal
:
import typing
def get(key: typing.Literal['1','2','3']) -> str:
return VALUES[key]
As was suggested in the comments, the enum
module provides a nice solution here.正如评论中所建议的,
enum
模块在这里提供了一个很好的解决方案。 By mixing in str
with enum.Enum
, we can create an Enum
that is fully backwards-compatible with str
(ie, can be used wherever a str
type is expected.通过将
str
与enum.Enum
混合,我们可以创建一个与str
完全向后兼容的Enum
(即,可以在需要str
类型的任何地方使用。
from enum import Enum
# The mixin type has to come first if you're combining
# enum.Enum with other types
class Values(str, Enum):
N1 = 'One'
N2 = 'Two'
N3 = 'Three'
If we enter this definition into the interactive console, we'll see that this class has the following behaviour:如果我们将此定义输入到交互式控制台中,我们将看到该类具有以下行为:
>>> Values['N1']
<Values.N1: 'One'>
>>> Values('One')
<Values.N1: 'One'>
>>> Values.N1
<Values.N1: 'One'>
>>> Values('One') is Values.N1 is Values['N1']
True
>>> Values.N1.name
'N1'
>>> Values.N1.value
'One'
>>> Values.N1 == 'One'
True
>>> Values.N1 is 'One'
False
>>> Values.N1.startswith('On')
True
>>> type(Values.N1)
<enum 'Values'>
>>> for key in Values:
... print(key)
...
Values.N1
Values.N2
Values.N3
>>> list(Values)
[Values.N1, Values.N2, Values.N3]
As you can see, we have defined a new type which:如您所见,我们定义了一个新类型:
str
— it can freely be compared with str
objects, and str
methods can be used on its members.str
完全向后兼容——它可以自由地与str
对象进行比较,并且可以对其成员使用str
方法。typing.Literal
.typing.Literal
的替代typing.Literal
。 If I have a function like this:def do_something(some_string):
if some_string not in ('One', 'Two', 'Three'):
raise Exception('NO.')
then I can either annotate it like this:然后我可以像这样注释它:
from typing import Literal
def do_something(some_string: Literal['One', 'Two', 'Three']) -> None:
...
or like this (in which case you'll have to pass in a member of the Values
enum rather than a vanilla string, or the type-checker will raise an error):或者像这样(在这种情况下,您必须传入
Values
枚举的成员而不是普通字符串,否则类型检查器将引发错误):
# Values enum as defined above
def do_something(some_string: Values) -> None:
...
There's an even more detailed guide to the intricacies of python Enum
s here .这里有一个更详细的指导蟒的复杂性
Enum
Ş这里。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.