在Python中定义另一个类中的类有什么好处?

问题描述 投票:87回答:6

我在这里谈论的是嵌套类。基本上,我有两个我正在建模的类。 DownloadManager类和DownloadThread类。这里显而易见的OOP概念是构图。然而,构图并不一定意味着嵌套,对吧?

我的代码看起来像这样:

class DownloadThread:
    def foo(self):
        pass

class DownloadManager():
    def __init__(self):
        dwld_threads = []
    def create_new_thread():
        dwld_threads.append(DownloadThread())

但现在我想知道是否存在嵌套会更好的情况。就像是:

class DownloadManager():
    class DownloadThread:
        def foo(self):
            pass
    def __init__(self):
        dwld_threads = []
    def create_new_thread():
        dwld_threads.append(DownloadManager.DownloadThread())
python oop
6个回答
106
投票

当“内部”类是一次性时,你可能想要这样做,它永远不会在外部类的定义之外使用。例如,要使用元类,它有时候很方便

class Foo(object):
    class __metaclass__(type):
        .... 

如果您只使用一次,而不是单独定义元类。

我唯一一次使用这样的嵌套类,我只使用外部类作为命名空间将一堆密切相关的类组合在一起:

class Group(object):
    class cls1(object):
       ...

    class cls2(object):
       ...

然后从另一个模块,你可以导入Group并将它们称为Group.cls1,Group.cls2等。但是有人可能会说你可以通过使用模块完成相同的工作(可能以一种不那么混乱的方式)。


19
投票

我不懂Python,但你的问题似乎很笼统。如果它特定于Python,请忽略我。

类嵌套完全是关于范围的。如果你认为一个类只在另一个类的上下文中有意义,那么前者可能是成为嵌套类的一个很好的候选者。

这是一个常见的模式,将辅助类作为私有嵌套类。


6
投票

除非您正在处理元类,否则执行此操作确实没有任何好处。

班级:套房真的不是你想象的那样。这是一个奇怪的范围,它做了奇怪的事情。它真的甚至不上课!它只是收集一些变量的一种方式 - 类的名称,基础,属性的小字典和元类。

名称,字典和基础都被传递给元类的函数,然后将它分配给类:suite所在范围内的变量“name”。

通过弄乱元类,实际上通过在库存标准类中嵌套类,你可以获得什么,更难以阅读代码,更难理解代码,以及奇怪的错误,如果不熟悉“类”的原因,这些错误非常难以理解scope与任何其他python范围完全不同。


5
投票

您可以使用类作为类生成器。喜欢(在一些袖口代码:)

class gen(object):
    class base_1(object): pass
    ...
    class base_n(object): pass

    def __init__(self, ...):
        ...
    def mk_cls(self, ..., type):
        '''makes a class based on the type passed in, the current state of
           the class, and the other inputs to the method'''

我觉得当你需要这个功能时,你会非常清楚。如果你不需要做类似的事情,它可能不是一个好的用例。


4
投票

当需要构建其增强功能封装在特定嵌套类中的继承类时,嵌套类还有另一种用法。

看这个例子:

class foo:

  class bar:
    ...  # functionalities of a specific sub-feature of foo

  def __init__(self):
    self.a = self.bar()
    ...

  ...  # other features of foo


class foo2(foo):

  class bar(foo.bar):
    ... # enhanced functionalities for this specific feature

  def __init__(self):
    foo.__init__(self)

请注意,在foo的构造函数中,当正在构造的对象实际上是self.a = self.bar()对象时,行foo.bar将构造foo,并且当构造的对象实际上是foo2.bar对象时,foo2对象将构造bar

如果类foo在类bar2之外被定义,以及它的继承版本(例如,将被称为foo2),那么定义新类foo2会更加痛苦,因为self.a = bar2()的构造函数需要有它的第一行被qazxswpoi取代,这意味着重写整个构造函数。


1
投票

不,构图并不意味着嵌套。如果要在外部类的命名空间中更多地隐藏它,那么有一个嵌套类是有意义的。

无论如何,我认为在你的情况下没有任何实际的嵌套用法。这将使代码更难以阅读(理解),并且它还会增加缩进,这会使行更短并且更容易分裂。

© www.soinside.com 2019 - 2024. All rights reserved.