it-swarm-pt.tech

Existe um benefício em definir uma classe dentro de outra classe no Python?

O que eu estou falando aqui são classes aninhadas. Basicamente, tenho duas classes que estou modelando. Uma classe DownloadManager e uma classe DownloadThread. O conceito óbvio OOP aqui é composição. No entanto, composição não significa necessariamente aninhamento, certo?

Eu tenho um código que se parece com isso:

class DownloadThread:
    def foo(self):
        pass

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

Mas agora estou me perguntando se há uma situação em que o assentamento seria melhor. Algo como:

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

Você pode fazer isso quando a classe "interna" for única, que nunca será usada fora do definição da classe externa. Por exemplo, para usar uma metaclasse, às vezes é útil fazer

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

em vez de definir uma metaclasse separadamente, se você estiver usando apenas uma vez.

A única outra vez em que usei classes aninhadas dessa maneira, usei a classe externa apenas como um espaço para nome para agrupar várias classes intimamente relacionadas:

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

    class cls2(object):
       ...

Em seguida, de outro módulo, você pode importar Group e se referir a eles como Group.cls1, Group.cls2 etc. No entanto, pode-se argumentar que você pode realizar exatamente o mesmo (talvez de uma maneira menos confusa) usando um módulo.

108
dF.

Não conheço Python, mas sua pergunta parece muito geral. Ignore-me se for específico para Python.

O aninhamento de classe tem tudo a ver com escopo. Se você acha que uma classe só faz sentido no contexto de outra, então a primeira provavelmente é um bom candidato para se tornar uma classe aninhada.

É um padrão comum fazer classes auxiliares como classes privadas e aninhadas.

18
André Chalella

Realmente não há benefício em fazer isso, exceto se você estiver lidando com metaclasses.

a classe: suite realmente não é o que você pensa que é. É um escopo estranho, e faz coisas estranhas. Realmente nem faz aula! É apenas uma maneira de coletar algumas variáveis ​​- o nome da classe, as bases, um pequeno dicionário de atributos e uma metaclasse.

O nome, o dicionário e as bases são todos passados ​​para a função que é a metaclasse e, em seguida, são atribuídos à variável 'name' no escopo em que a classe: suite estava.

O que você pode ganhar mexendo com metaclasses e, de fato, aninhando classes em suas classes padrão de ações, é mais difícil de ler código, mais difícil de entender código e erros estranhos que são terrivelmente difíceis de entender sem estar intimamente familiarizado com o porquê da 'classe' O escopo é totalmente diferente de qualquer outro escopo python.

6
Jerub

Você pode estar usando uma classe como gerador de classes. Como (em alguns códigos fora do punho :)

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'''

Sinto que quando você precisar dessa funcionalidade, ficará muito claro para você. Se você não precisa fazer algo semelhante, provavelmente não é um bom caso de uso.

5
tim.tadh

Há outro uso para a classe aninhada, quando se deseja construir classes herdadas cujas funcionalidades aprimoradas são encapsuladas em uma classe aninhada específica.

Veja este exemplo:

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)

Observe que, no construtor de foo, a linha self.a = self.bar() criará um foo.bar Quando o objeto que está sendo construído for realmente um objeto foo e um foo2.bar Quando o objeto que está sendo construído é realmente um objeto foo2.

Se a classe bar foi definida fora da classe foo, bem como sua versão herdada (que seria chamada bar2 Por exemplo), defina a nova classe foo2 Seria muito mais doloroso, porque o construtor de foo2 Precisaria ter sua primeira linha substituída por self.a = bar2(), o que implica reescrever todo o construtor.

4
Thomas

Não, composição não significa aninhamento. Seria bom ter uma classe aninhada se você deseja ocultá-la mais no espaço de nomes da classe externa.

De qualquer forma, não vejo nenhum uso prático para aninhar no seu caso. Isso tornaria o código mais difícil de ler (entender) e também aumentaria a indentação, o que tornaria as linhas mais curtas e mais propensas à divisão.

1
Cristian Ciupitu