是否可以从 __init__.py 扩展 class

Is it possible to extend a class from __init__.py

我写了一个小的 python 包,它用一些额外的方法扩展了 pandas 数据框。

目前,我的包裹中有此代码:

def init():
    @pd.api.extensions.register_dataframe_accessor("test")
    class _:
        def __init__(self, pandas_obj):
            self._obj = pandas_obj

        def myMethod(self):
            pass

然后我在 python 中执行以下操作:

import pandas as pd
import mypackage as mp
mp.init()
test = pd.Dataframe(<define data frame>)
test.mp.myMethod()

我的问题是,是否可以在 mypackage 的 __init__.py 中执行 pandas 导入和注册访问器,这样一旦导入 mypackage,我就可以自动访问 mymethod 而无需初始化()步骤?我目前的做法感觉有点笨拙...

我可能遗漏了您的问题中的某些内容,但我认为您可能找错了树。在这方面,__init__.py 没有什么特别之处——您在 __init__.py 中编写的任何内容都会在您导入包时执行,所以我认为您根本不需要 init() 函数。如果您的文件包含:

# mypackage/__init__.py
import pandas as pd


@pd.api.extensions.register_dataframe_accessor("test")
class _:
    def __init__(self, pandas_obj):
        self._obj = pandas_obj

    def myMethod(self):
        print(self._obj)

现在您只需导入 mypackage 即可使用它,例如:

>>> import pandas as pd
>>> import mypackage
>>> df = pd.DataFrame({'a': [1, 2, 3]})
>>> df.test.myMethod()
   a
0  1
1  2
2  3

顺便说一句,您可能明确 想要 类似 init() 函数的一个原因是最小惊奇原则:因为 register_dataframe_accessor 修改了DataFrame 所有用户(包括其他库)的实例有很小的可能性,您的 register_dataframe_accessor,仅通过导入您的包,如果它们碰巧共享相同的名称,可能会覆盖其他包的数据帧访问器。

如果名称相当独特,这可能不是问题。它也可能根本不是您的包的问题,​​具体取决于它的使用方式。