我想这样做:
from functools import partial
from typing import DefaultDict
def five() -> int:
return 5 # whatever.
MyDefaultDict = partial(DefaultDict[str, int], five)
my_mapping: MyDefaultDict = MyDefaultDict(x=4)
print(my_mapping['x'])
print(my_mapping['y'])
- 新的类型/类的东西
MyDefaultDict
声明一次,并有一个单一的名称。 MyDefaultDict
可以像一个类构造函数一样使用,它的签名与dict
相同,唯一的区别是你得到的是一个defaultdict
与five
作为它的工厂。- MyPy应该理解
MyDefaultDict
与相同(或者最好是的子类)DefaultDict[str, int]
。这是上面代码中不能工作的部分。 - 对于我当前的使用来说是不必要的,但在一般情况下是很好的:
MyDefaultDict
实际上应该具有类属性(例如。静态方法)继承自defaultdict
。
partial
不合适并不奇怪。一般来说,partial
与MyPy的关系很差,而在最好的情况下将被理解为返回某种Callable
,这对于my_mapping
来说不是一个明智的类型。(实际报告的故障为"scratch.py:9: error: Variable "scratch.MyDefaultDict" is not valid as a type
"。)
许多其他的事情似乎可以工作,但我还没能让他们:
子类和重写__init__
class MyDefaultDict(DefaultDict[str, int]):
def __init__(self, *args, **kwargs):
DefaultDict[str, int].__init__(self, five, *args, **kwargs)
MyPy。
文件"scratch.py",第9行,在
__init__
DefaultDict[str, int].__init__(self, five, *args, **kwargs)
TypeError:__init__()
得到一个意外的关键字参数'x'
子类和重写__new__
class MyDefaultDict(DefaultDict[str, int]):
def __new__(cls, *args, **kwargs):
return super().__new__(cls, five, *args, **kwargs)
MyPy。
"KeyError: 'y'
";未使用工厂功能
将partial
包裹起来,使其看起来像一个类型
我尝试了type
与三个参数,typing.NewType
和types.new_class
。据我所知,这不是他们打算解决的问题。
我简单地研究了一下元类,并没有看到它们如何帮助解决这个问题。
我正在使用python 3.8,但其他版本的答案可能是可行的。
有谁知道这样做的正确方法吗?
在写上面的时候,我意识到覆盖__init__
的不同方式会产生不同的结果。
这个也不能用:
class MyDefaultDict(DefaultDict[str, int]):
def __init__(self, *args, **kwargs):
super().__init__(self, five, *args, **kwargs)
File "scratch.py",第9行,
__init__
super().__init__(self, five, *args, **kwargs)
TypeError:第一个参数必须是可调用的或None
这个做工作;理解为什么:会很好
class MyDefaultDict(DefaultDict[str, int]):
def __init__(self, *args, **kwargs):
super().__init__(five, *args, **kwargs)