Python中构造函数**kwargs的签名继承与多TypedDict适配
复用基于TypedDict的类构造函数
问题场景
我定义了如下两个TypedDict类型:
class TypeFilter1(TypedDict): c: str d: float class TypeFilter2(TypedDict): e: float f: int
并基于它们实现了两个类,构造函数会解析**kwargs,仅保留对应TypedDict注解中的键值对,格式化为参数字符串:
class MyClass1(): def __init__(self, **kwargs:Unpack[TypeFilter1]) -> None: self.filters = [f"{key}:{values}" for key, values in kwargs.items() if key in TypeFilter1.__annotations__ ] self.params = ' '.join(self.filters) class MyClass2(): def __init__(self, **kwargs:Unpack[TypeFilter2]) -> None: self.filters = [f"{key}:{values}" for key, values in kwargs.items() if key in TypeFilter2.__annotations__ ] self.params = ' '.join(self.filters)
示例使用:
a = MyClass1(c="hello", d=2.0) # self.params -> "c:hello d:2.0" b = MyClass2(e=2.1, g=3) # self.params -> "e:2.1"
由于两个类逻辑完全一致,希望通过继承基类复用构造函数,但尝试泛型、Any类型等方式均未成功,请问该如何实现?若存在N个TypeFilter,又该如何处理?
解决方案
可以通过泛型基类+类变量指定TypedDict类型的方式实现复用,具体步骤如下:
1. 定义泛型基类
导入必要模块后,创建泛型基类,通过类属性接收子类对应的TypedDict类型,同时用TypeVar约束泛型类型为TypedDict子类:
from typing import TypedDict, Unpack, TypeVar, Generic # 约束泛型变量为TypedDict的子类 T = TypeVar('T', bound=TypedDict) class BaseFilterClass(Generic[T]): # 子类需重写该属性,绑定对应的TypedDict类型 filter_type: type[T] def __init__(self, **kwargs: Unpack[T]) -> None: # 利用类属性获取TypedDict注解,过滤有效键值对 self.filters = [f"{key}:{value}" for key, value in kwargs.items() if key in self.filter_type.__annotations__] self.params = ' '.join(self.filters)
2. 实现子类
子类仅需继承基类,并指定filter_type为目标TypedDict,无需重复编写构造函数:
class MyClass1(BaseFilterClass[TypeFilter1]): filter_type = TypeFilter1 class MyClass2(BaseFilterClass[TypeFilter2]): filter_type = TypeFilter2
3. 验证效果
使用方式与原代码完全一致,且类型提示依然有效:
a = MyClass1(c="hello", d=2.0) print(a.params) # 输出: c:hello d:2.0 b = MyClass2(e=2.1, g=3) print(b.params) # 输出: e:2.1
处理N个TypeFilter的情况
若存在N个TypeFilter,只需为每个TypeFilter创建对应子类,仅指定filter_type属性即可,完全复用基类逻辑。例如新增TypeFilter3:
class TypeFilter3(TypedDict): x: bool y: str class MyClass3(BaseFilterClass[TypeFilter3]): filter_type = TypeFilter3
使用时逻辑一致:
c = MyClass3(x=True, y="test", z=100) print(c.params) # 输出: x:True y:test
内容的提问来源于stack exchange,提问作者ddgg
相关产品推荐
相关产品推荐

