继承与熊猫

时间:2017-10-03 13:32:33

标签: python-3.x pandas inheritance

我正在尝试基于Pandas'ExcelWriter创建一个文件编写器。我继续像往常一样继续使用Python(3)中的类继承:

import pandas as pd

class Writer(pd.ExcelWriter):
    def __init__(self, fname, engine='openpyxl'):
        pd.ExcelWriter.__init__(self, fname, engine=engine)
        self.newvar = 0

但是,当我尝试使用它时,我无法访问newvar

test = Writer('test.xlsx')
test.newvar

返回:

AttributeError: '_XlsxWriter' object has no attribute 'nmax'

当我检查test的类型时,它会返回:

pandas.io.excel._XlsxWriter  

我不明白自己错过了什么,因为我在很多其他情况下都使用过这种继承。任何想法都将不胜感激!

1 个答案:

答案 0 :(得分:3)

这是因为pandas.ExcelWriter.__new__返回的是与自身不同的类(实际上它是abc.ABCMeta)。根据文件路径的扩展名和使用的引擎选择类 - 当您检查新创建的实例的类型时,您可以观察到该类。这意味着调用返回的任何类的__init__方法。您可以将ExcelWriter视为每种格式和引擎的特定编写器的某种代理(尽管它也定义了这样的编写者必须提供的API)。

为了使您的作家可用(对于给定的引擎),您需要register它。

但在您可以这样做之前,您需要按照help(pandas.ExcelWriter)找到的说明进行兼容。为了完整起见,我在这里引用它们:

# Defining an ExcelWriter implementation (see abstract methods for more...)

# - Mandatory
#   - ``write_cells(self, cells, sheet_name=None, startrow=0, startcol=0)``
#     --> called to write additional DataFrames to disk
#   - ``supported_extensions`` (tuple of supported extensions), used to
#      check that engine supports the given extension.
#   - ``engine`` - string that gives the engine name. Necessary to
#     instantiate class directly and bypass ``ExcelWriterMeta`` engine
#     lookup.
#   - ``save(self)`` --> called to save file to disk
# - Mostly mandatory (i.e. should at least exist)
#   - book, cur_sheet, path

# - Optional:
#   - ``__init__(self, path, engine=None, **kwargs)`` --> always called
#     with path as first argument.

因此,我们可以扩展你的课程:

class Writer(pd.ExcelWriter):
    engine = 'openpyxl'
    supported_extensions = ('xlsx',)

    def write_cells(self, cells, sheet_name=None, startrow=0, startcol=0):
        # Implement something useful here.
        pass

    def save(self):
        # Implement something useful here.
        pass

    def __init__(self, fname, engine='openpyxl', **kwargs):
        super().__init__(self, fname, engine=engine, **kwargs)

现在您可以使用pd.io.excel.register_writer(Writer)注册编写器。但是您需要确保您指定的引擎与openpyxl版本匹配。您可以查看特定作者的选择过程here;可以通过print(pd.io.excel._writers)检查当前为每个版本注册的作者。

作为旁注:你也可以将一个已经可用的特定作者子类化,并重用他们的write_cellssave方法(但是在这种情况下你也需要注册你的作者) ):