Python无单一父类场景的类型提示:Sklearn缩放器标注咨询
问题解答
1. 恰当的类型提示方式
有两种更优雅的方案,比直接写Union或硬编码具体类更合适:
基于公共父类组合:既然所有目标缩放器都继承自
OneToOneFeatureMixin、TransformerMixin、BaseEstimator,可以直接用这三个类的组合作为类型提示(Python 3.10+支持|操作符表示类型并集):from sklearn.base import OneToOneFeatureMixin, TransformerMixin, BaseEstimator from abc import ABC import pandas as pd class FeatureEngineering(ABC): def __init__(self, dataframe: pd.DataFrame, scaler: OneToOneFeatureMixin | TransformerMixin | BaseEstimator | None = None): self.dataframe = dataframe self.scaler = scaler这种方式直接利用现有继承关系,静态检查工具能准确识别合规的缩放器类型。
基于协议(Protocol):定义一个仅关注核心行为的协议,只要类实现了缩放器必备的方法,就会被视为符合该类型,这种方式更灵活,不局限于sklearn的继承体系:
from typing import Protocol import pandas as pd from abc import ABC class ScalerProtocol(Protocol): def fit(self, X: pd.DataFrame, y=None) -> "ScalerProtocol": ... def transform(self, X: pd.DataFrame) -> pd.DataFrame: ... def fit_transform(self, X: pd.DataFrame, y=None) -> pd.DataFrame: ... class FeatureEngineering(ABC): def __init__(self, dataframe: pd.DataFrame, scaler: ScalerProtocol | None = None): self.dataframe = dataframe self.scaler = scaler自定义缩放器只要实现上述方法,就能被正确识别为合规类型。
2. Python允许创建特定类型,实现方式如下
可以通过三种方式为该场景创建专属类型:
使用
TypeAlias定义类型别名:轻量化地给现有类型组合起一个语义清晰的别名,静态检查时等价于原类型:from typing import TypeAlias from sklearn.base import OneToOneFeatureMixin, TransformerMixin, BaseEstimator GeneralScaler: TypeAlias = OneToOneFeatureMixin | TransformerMixin | BaseEstimator # 用法示例 class FeatureEngineering(ABC): def __init__(self, dataframe: pd.DataFrame, scaler: GeneralScaler | None = None): self.dataframe = dataframe self.scaler = scaler使用
NewType创建语义类型:给类型赋予专属名称,仅用于静态类型检查,运行时不会做额外限制:from typing import NewType from sklearn.base import OneToOneFeatureMixin, TransformerMixin, BaseEstimator GeneralScaler = NewType("GeneralScaler", OneToOneFeatureMixin | TransformerMixin | BaseEstimator) # 用法示例 class FeatureEngineering(ABC): def __init__(self, dataframe: pd.DataFrame, scaler: GeneralScaler | None = None): self.dataframe = dataframe self.scaler = scaler使用
TypeVar绑定约束类型:创建一个受约束的类型变量,限定只能是同时继承指定父类的类型,检查更严谨:from typing import TypeVar from sklearn.base import OneToOneFeatureMixin, TransformerMixin, BaseEstimator ScalerType = TypeVar("ScalerType", bound=OneToOneFeatureMixin & TransformerMixin & BaseEstimator) # 用法示例 class FeatureEngineering(ABC): def __init__(self, dataframe: pd.DataFrame, scaler: ScalerType | None = None): self.dataframe = dataframe self.scaler = scaler
内容的提问来源于stack exchange,提问作者An old man in the sea.
相关产品推荐
相关产品推荐

