Swifter库如何通过导入为Pandas对象新增属性?
问题:导入Swifter后为何能给Pandas Series/DataFrame新增属性?
我发现Swifter库可加速Python中Pandas Series的处理,其底层会做向量化处理与优化。但我好奇为何仅通过导入该库,就能为Pandas Series或DataFrame对象新增属性?此前我认为导入语句仅能引入新类、函数等,无法修改已有命名空间中对象的API,这与我对OOP中对象交互的认知冲突,想了解其实现方式及所用Python高级特性。
极简示例代码:
#!/usr/bin/env python3 # encoding: utf-8 import pandas as pd # Version 1.4.1 import numpy as np # Version 1.22.3 samples:int=2**20 colname:str='Value' frame=pd.DataFrame(data={colname:np.random.randint(low=0, high=45353, size=samples)}) import swifter # Version 1.22.3 The following line throws an attribute error without this import frame[colname].swifter # With swifter imported, this is swifter.SeriesAccessor object
解答
核心原因是Swifter利用了Python的动态特性(猴子补丁)结合Pandas官方提供的访问器注册机制,具体拆解如下:
1. Pandas的访问器注册机制
Pandas本身提供了官方扩展接口,允许第三方库为Series/DataFrame添加自定义属性:
- 使用
pd.api.extensions.register_series_accessor("swifter")可以给所有Series对象注册一个名为swifter的属性 - 使用
pd.api.extensions.register_dataframe_accessor("swifter")可以给所有DataFrame对象注册同名属性
注册后,无论导入Swifter之前还是之后创建的Series/DataFrame实例,都会自动拥有.swifter属性,该属性会返回你定义的访问器类实例(比如Swifter中的SeriesAccessor)。
2. Swifter的导入执行逻辑
当你执行import swifter时,Swifter模块的顶层初始化代码会自动执行:
- 它会定义好
SeriesAccessor和DataFrameAccessor类,这两个类封装了Swifter的核心加速逻辑 - 然后调用Pandas的上述注册函数,把这两个类绑定到Series和DataFrame的
.swifter属性上
这一步就是动态修改了Pandas原生类的结构,属于Python中典型的猴子补丁(Monkey Patching)——在运行时修改已有类的属性或方法,而不需要修改类的原始源代码。
3. 为什么和你的原有认知冲突?
你之前认为导入不能修改已有对象API,是基于静态语言的思维,但Python是动态语言:
- 类的结构不是编译时固定的,运行时可以随时添加、修改、删除类的属性
- 模块导入时会执行其顶层代码,Swifter正是利用这一点,在导入阶段完成了对Pandas类的扩展
这种机制是Pandas官方鼓励的扩展方式,很多第三方库都用了相同的模式来扩展Pandas对象的功能。
内容的提问来源于stack exchange,提问作者Della
相关产品推荐
相关产品推荐

