将类嵌套在Python的3层深处——这是一种糟糕的做法吗?

将类嵌套在Python的3层深处——这是一种糟糕的做法吗?,python,class,oop,subclass,Python,Class,Oop,Subclass,我正在编写一个Python脚本,用于与XLS/XLSX/CSV电子表格交互。有三个主要类彼此嵌套(不彼此扩展,这些类实际上位于另一个类中) 以下对三个初级班进行了说明: 主工作簿类,它是XLS/XLSX/CSV类的工厂方法。这是可以从外部访问的 工作簿类中的专用工作表类,用于打开文件本身中的特定电子表格或工作表。这只能通过Workbook.worksheet()方法访问 \uu工作表类中的私有\uu单元格类,它与单元格本身交互。这不应该从外部访问,而应该只能通过\u工作表类访问 以下是迄今为止类

我正在编写一个Python脚本,用于与XLS/XLSX/CSV电子表格交互。有三个主要类彼此嵌套(彼此扩展,这些类实际上位于另一个类中)

以下对三个初级班进行了说明:

  • 工作簿
    类,它是XLS/XLSX/CSV类的工厂方法。这是可以从外部访问的
  • 工作簿
    类中的专用
    工作表
    类,用于打开文件本身中的特定电子表格或工作表。这只能通过
    Workbook.worksheet()
    方法访问
  • \uu工作表
    类中的私有
    \uu单元格
    类,它与单元格本身交互。这不应该从外部访问,而应该只能通过
    \u工作表
    类访问
  • 以下是迄今为止类结构的简化版本:

    类工作簿(对象):
    定义初始化(自我,文件名):
    self.\u文件名=文件名
    def工作表(自我,姓名):
    返回self.\u工作表(self,name)
    类工作表():
    定义初始化(自我、工作簿、工作表):
    self.\uuu工作簿=工作簿
    def单元(自身,单元id,数据=无):
    返回自我。单元格(单元格id,数据)
    类_单元格():
    def u uu init u uuu(self,cell,data=None):
    self.\u单元=单元
    self.\uuu data=数据
    def setVal(自身,数据):
    self.\uuu data=数据
    定义(自我):
    返回自身数据
    工作簿=工作簿('test file.csv')
    工作表=工作簿。工作表(‘第一个工作表’)
    单元格_A1=工作表。单元格('A1','Foo…'))
    打印(“前-单元格A1:%s”%Cell#A1)#=>前-单元格A1:Foo。。。
    单元格_A1.setVal('Bar…'))
    打印(“单元格A1之后:%s”%Cell#A1)#=>单元格A1之前-之后:条形图。。。
    
    所以我的问题是,在一个班级内,在一个班级内上课被认为是不好的做法吗


    我对Python有些陌生,我的经验主要是PHP/JS/Perl。在Python中,在一个类中包含一个类似乎并不少见,但出于某种原因,将一个类嵌套到3层似乎是错误的。如果是的话,而且有更好的方法,那就太好了

    我知道另一种选择是不嵌套类,只需检查
    工作簿
    的实例是否作为参数提供给
    工作表
    。然后在
    工作簿
    中创建一个方法,该方法仅在
    工作表
    中返回一个实例,同时将
    self
    作为用于启动它的参数之一处理

    例如:

    类工作簿(对象):
    定义初始化(自我,文件名):
    self.\u文件名=文件名
    def工作表(自我,姓名):
    返回self.Worksheet(self,name)
    类工作表(对象):
    定义初始化(自我,工作簿,工作表=0):
    如果不存在(工作簿、工作簿):
    引发异常('预期工作簿是工作簿类的实例')
    self.\uuu工作簿=工作簿
    def单元(自身,单元id,数据=无):
    返回self.Cell(Cell\u id,data)
    类单元格(对象):
    定义初始化(self、工作表、单元格、数据=无):
    如果不存在(工作表、工作表):
    引发异常('预期工作表是工作表类的实例')
    self.\u单元=单元
    self.\uuu data=数据
    def setVal(自身,数据):
    self.\uuu data=数据
    定义(自我):
    返回自身数据
    #示例用法1
    工作簿=工作簿('test file.xls')
    工作表=工作簿。工作表(‘第一个工作表’)
    单元格_A1=工作表。单元格('A1','Foo…'))
    打印(“前-单元格A1:%s”%Cell#A1)#=>前-单元格A1:Foo。。。
    单元格_A1.setVal('Bar…'))
    打印(“单元格A1之后:%s”%Cell#A1)#=>单元格A1之前-之后:条形图。。。
    #示例用法二
    工作簿=工作簿('test file.xlsx')
    工作表=工作表(工作簿“第一个工作表”)
    单元格_A1=单元格(工作表'A1','Foo…')
    打印(“前-单元格A1:%s”%Cell#A1)#=>前-单元格A1:Foo。。。
    单元格_A1.setVal('Bar…'))
    打印(“单元格A1之后:%s”%Cell#A1)#=>单元格A1之前-之后:条形图。。。
    #失败的例子
    工作表=工作表(“非工作表”,1)#=>异常,如预期
    
    但是,这种替代方法意味着可以从外部访问
    工作表
    单元格
    类,并且可以手动启动这些类。。。但我想这不是一件可怕的事情

    让我知道你认为最好的路线是什么! 本文中的一条评论提供了一个链接,用户在其中发布了嵌套类的3个优点,第一个是:

    类的逻辑分组:如果一个类只对另一个类有用,那么将其嵌入该类并将两者保持在一起是合乎逻辑的。嵌套这样的“助手类”使它们的包更加精简


    这正是我所想的。我只是觉得把它们嵌套到3层有点尴尬,因为我以前只做过2层。

    把你的问题转过来:把类写成嵌套类有什么好处吗?与函数不同,类不使用“词法作用域”(即,与函数不同,无法从当前类的命名空间解析的名称不会从周围的类解析)。这就是为什么您必须参考与
    工作簿
    实例相关的
    工作表

    这反过来意味着,您使用的嵌套没有明显的优势,尽管它会起作用。大多数有经验的Python程序员可能在编写示例时不使用嵌套。这简化了代码(因为类名对于包含的模块都是全局的)

    请注意,这与declari完全不同
    worksheet = workbook['First Worksheet']
    worksheet['A1'] = 'Foo...'
    
    class Workbook:
        # : : :
        worksheet_type = Worksheet
        # : : :
        def worksheet(self, name):
            return self.worksheet_type(self, name)
    
    class WorkbookVariant(Workbook):
        # : : :
        worksheet_type = WorkbookVariant