在 Python 中深度嵌套类 3 层 - 这是不好的做法吗?

Jus*_*tin 3 python oop class subclass

我正在工作中编写一个 Python 脚本,用于与 XLS/XLSX/CSV 电子表格进行交互。存在三个相互嵌套的主要类(相互扩展,这些类实际上位于另一个类内部)

三个主要类解释如下:

  1. Workbook类,它是 XLS/XLSX/CSV 类的工厂方法。这是可以从外部访问的
  2. __Worksheet类中的私有类Workbook,用于打开文件本身中的特定电子表格或工作表。这只能通过Workbook.worksheet()方法访问
  3. __Cell类中的私有类__Worksheet,与单元本身交互。这不应该从外部访问,而只能通过__Worksheet类访问

这是迄今为止类结构的简化版本:

class Workbook( object ):

    def __init__( self, file_name ):
        self.__file_name = file_name

    def worksheet( self, name ):
        return self.__Worksheet( self, name )

    class __Worksheet():
        def __init__( self, workbook, worksheet ):
            self.__workbook = workbook

        def cell( self, cell_id, data = None ):
            return self.__Cell( cell_id, data )

        class __Cell():
            def __init__( self, cell, data = None ):
                self.__cell = cell
                self.__data = data

            def setVal( self, data ):
                self.__data = data

            def __str__( self ):
                return self.__data

workbook = Workbook( 'test-file.csv' )
worksheet = workbook.worksheet( 'First Worksheet' )
cell_A1 = worksheet.cell('A1', 'Foo...')

print("Before - Cell A1: %s" % cell_A1) # => Before - Cell A1: Foo...
cell_A1.setVal('Bar...')
print("After - Cell A1: %s" % cell_A1)  # => Before - After - Cell A1: Bar...
Run Code Online (Sandbox Code Playgroud)

所以我的问题是——在类中类、类内类中开设类是否被认为是不好的做法?

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

我知道替代方法是嵌套类,而只检查是否将 的实例作为参数Workbook给出。Worksheet然后创建一个方法,其中Workbook仅返回一个实例 if Worksheet,同时self作为用于启动它的参数之一进行处理。

例子:

class Workbook( object ):
    def __init__( self, file_name ):
        self.__file_name = file_name

    def worksheet( self, name ):
        return self.Worksheet( self, name )

class Worksheet( object ):
    def __init__( self, workbook, worksheet = 0 ):
        if not isinstance( workbook, Workbook ):
            raise Exception( 'Expected the workbook to be an instance of the Workbook class' )

        self.__workbook = workbook

    def cell( self, cell_id, data = None ):
        return self.Cell( cell_id, data )

class Cell( object ):
    def __init__( self, worksheet, cell, data = None ):
        if not isinstance( worksheet, Worksheet ):
            raise Exception( 'Expected the worksheet to be an instance of the Worksheet class' )

        self.__cell = cell
        self.__data = data

    def setVal( self, data ):
        self.__data = data

    def __str__( self ):
        return self.__data

# Example Usage One
workbook = Workbook( 'test-file.xls' )
worksheet = workbook.worksheet( 'First Worksheet' )
cell_A1 = worksheet.cell('A1', 'Foo...')

print("Before - Cell A1: %s" % cell_A1) # => Before - Cell A1: Foo...
cell_A1.setVal('Bar...')
print("After - Cell A1: %s" % cell_A1)  # => Before - After - Cell A1: Bar...

# Example Usage Two
workbook = Workbook( 'test-file.xlsx' )
worksheet = Worksheet( workbook, 'First Worksheet' )
cell_A1 = Cell( worksheet, 'A1', 'Foo...')

print("Before - Cell A1: %s" % cell_A1) # => Before - Cell A1: Foo...
cell_A1.setVal('Bar...')
print("After - Cell A1: %s" % cell_A1)  # => Before - After - Cell A1: Bar...

# Failed Example
worksheet = Worksheet( 'Not worksheet', 1 ) # => Exception, as expected
Run Code Online (Sandbox Code Playgroud)

然而,这种替代方法意味着WorksheetCell类可以从外部访问并且可以手动启动......但我想这并不是一件可怕的事情。

让我知道您认为最好的路线是什么!这篇文章的一条评论提供了另一个 SO 帖子的链接,其中用户发布了嵌套类的 3 个优点,其中第一个是:

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

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

hol*_*web 6

扭转你的问题:将类编写为嵌套有什么优势吗?与函数不同,类不使用“词法作用域”(即与函数不同,无法从当前类的命名空间解析的名称将不会从周围的类解析)。这就是为什么您必须__Worksheet相对于 的实例引用该类Workbook

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

请注意,这与在函数体内声明类有很大不同。在这种情况下,类的代码可以引用函数命名空间中的变量,并且 Python 会竭尽全力确保这些引用仍然可供类使用,即使在函数调用终止并且与调用关联的本地命名空间已终止之后也是如此。被摧毁了。