Есть ли смысл определять класс внутри другого класса в Python?

То, о чем я говорю, это вложенные классы. По сути, у меня есть два класса, которые я моделирую. Класс DownloadManager и класс DownloadThread. Очевидная концепция ООП - это композиция. Однако состав не обязательно означает вложенность, правильно?

У меня есть код, который выглядит примерно так:

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())

Ответ 1

Возможно, вы захотите сделать это, когда "внутренний" класс является одноразовым, который никогда не будет использоваться вне определения внешнего класса. Например, для использования метакласса иногда бывает удобно делать

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

вместо определения метакласса отдельно, если вы используете его только один раз.

Единственный раз, когда я использовал вложенные классы, я использовал внешний класс только как пространство имен, чтобы группировать связку тесно связанных между собой классов:

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

    class cls2(object):
       ...

Затем из другого модуля вы можете импортировать Group и ссылаться на них как на Group.cls1, Group.cls2 и т.д. Однако можно утверждать, что вы можете сделать то же самое (возможно, менее запутанным образом) с помощью модуля.

Ответ 2

Я не знаю Python, но ваш вопрос кажется очень общим. Игнорируйте меня, если это относится к Python.

Вложенность классов - это область. Если вы считаете, что один класс будет иметь смысл только в контексте другого, то первый, вероятно, хороший кандидат, чтобы стать вложенным классом.

Это обычный шаблон, создающий классы-помощники как частные, вложенные классы.

Ответ 3

Вы можете использовать класс как генератор классов. Например (в некоторых случаях код манжеты:)

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

Для этого нет никакой пользы, кроме случаев, когда вы имеете дело с метаклассами.

класс: suite действительно не то, что вы думаете. Это странный масштаб, и это странные вещи. Это действительно даже не класс! Это всего лишь способ сбора некоторых переменных - имя класса, базы, небольшой словарь атрибутов и метакласс.

Имя, словарь и базы все передаются функции, которая является метаклассом, а затем она назначается переменной "имя" в области, где был класс: suite.

То, что вы можете получить, возившись с метаклассами, а также с помощью гнездования классов в ваших стандартных стандартных классах, сложнее читать код, сложнее понять код и нечетные ошибки, которые трудно понять, не будучи глубоко знакомы с тем, почему Область "класс" полностью отличается от любой другой области python.

Ответ 5

Нет, состав не означает гнездование. Было бы разумно иметь вложенный класс, если вы хотите скрыть его больше в пространстве имен внешнего класса.

Во всяком случае, я не вижу практического использования для гнездования в вашем случае. Это сделало бы код более трудным для чтения (понимания), и это также увеличит отступ, который сделает линии более короткими и более склонными к расщеплению.