数据抽象调度
项目描述
databackend
databackend
包允许您注册一个子类,而无需导入该子类本身。这对于实现可选依赖项上的操作非常有用。
示例
在这个示例中,我们将实现一个函数fill_na()
,该函数用于填充DataFrame中的缺失值。它支持来自两个流行库的DataFrame对象:pandas
和polars
。重要的是,这两个库都不需要安装。
设置
下面的代码为两个库中的每个DataFrame类定义了“抽象”父类。
from databackend import AbstractBackend
class AbstractPandasFrame(AbstractBackend):
_backends = [("pandas", "DataFrame")]
class AbstractPolarsFrame(AbstractBackend):
_backends = [("polars", "DataFrame")]
请注意,抽象类可以用作在issubclass()
和isinstance
中替换实际对象的占位符。
from pandas import DataFrame
issubclass(DataFrame, AbstractPandasFrame)
isinstance(DataFrame(), AbstractPandasFrame)
True
📝 注意,您可以使用
AbstractPandasFrame.register_backend("pandas", "DataFrame")
作为注册后端的另一种方式。
简单的fill_na:使用isinstance切换行为
下面的fill_na()
函数针对pandas和polars进行了自定义处理。
def fill_na(data, x):
if isinstance(data, AbstractPolarsFrame):
return data.fill_nan(x)
elif isinstance(data, AbstractPandasFrame):
return data.fillna(x)
else:
raise NotImplementedError()
请注意,在定义fill_na()
时不需要导入pandas
或polars
。
以下是调用fill_na()
的两个类型DataFrame的示例。
# test polars ----
import polars as pl
df = pl.DataFrame({"x": [1, 2, None]})
fill_na(df, 3)
# test pandas ----
import pandas as pd
df = pd.DataFrame({"x": [1, 2, None]})
fill_na(df, 3)
x
0 1.0
1 2.0
2 3.0
关键在于,用户可能只安装了pandas或只安装了polars。重要的是,进行isinstance检查不会导入任何库!
高级fill_na:通用函数调度
databackend
与 泛型函数分发 结合使用时表现出色。这是一种编程方法,你首先声明一个函数(例如 fill_na()
),然后在函数上注册每个后端特定的实现。
Python 内置了一个名为 functools.singledispatch
的函数来实现这一点。
以下是使用它的前一个 fill_na()
函数的示例。
from functools import singledispatch
@singledispatch
def fill_na2(data, x):
raise NotImplementedError(f"No support for class: {type(data)}")
# handle polars ----
@fill_na2.register
def _(data: AbstractPolarsFrame, x):
return data.fill_nan(x)
# handle pandas ----
@fill_na2.register
def _(data: AbstractPandasFrame, x):
return data.fillna(x)
注意两个重要的装饰器
@singledispatch
定义了一个默认函数。如果没有找到特定实现,则会调用此函数。@fill_na2.register
定义了函数的特定版本。
以下是一个示例。
# example ----
import pandas as pd
import polars as pl
df = pl.DataFrame({"x": [1, 2, None]})
fill_na2(df, 3)
df = pd.DataFrame({"x": [1, 2, None]})
fill_na2(df, 3)
x
0 1.0
1 2.0
2 3.0
工作原理
在底层,AbstractBackend
类的行为与 Python 内置的 abc.ABC
类 类似。
from abc import ABC
class MyABC(ABC):
pass
from io import StringIO
MyABC.register(StringIO)
# StringIO is a "virtual subclass" of MyABC
isinstance(StringIO("abc"), MyABC)
True
关键区别在于,你可以使用元组 ("<mod_name>", "<class_name>")
来指定虚拟子类。
当运行 issubclass(SomeClass, AbstractBackend)
时...
- 检查标准 ABC 缓存机制,并可能立即返回答案。
- 否则,子类挂钩将遍历注册的后端。
- 挂钩将运行任何已导入的后端的子类检查(例如,位于
sys.modules
中)。
技术上,AbstractBackend
从 abc.ABCMeta
继承了所有有用的元类功能,因此也可以使用这些功能。
项目详情
下载文件
下载适合您平台的应用程序。如果您不确定要选择哪一个,请了解更多关于 安装包 的信息。
源分布
构建分布
databackend-0.0.3.tar.gz 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 3f047f21b5d92dcfdc85545c679d024b6595bb10a72bd61ef514d8f5857e22f9 |
|
MD5 | bbef86bd675e90c3e82fac668ad0d14a |
|
BLAKE2b-256 | 5afb0f8c739f42008957e4ba334cbf3d0b512946ed6d120e912d3f63f9f1d550 |
databackend-0.0.3-py3-none-any.whl 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 2ded97ff85a0ca272d752fbc0513f70512d2c23325e3c72de15613df7e959ef5 |
|
MD5 | 89358b256a79b82cafd3c5257873ef52 |
|
BLAKE2b-256 | d784582e1daf3f2eb296573c11b774abf10223e9858d4c5c936180b643a720 |