2008-09-17 21 views
73

De lo que estoy hablando aquí son clases anidadas. Esencialmente, tengo dos clases que estoy modelando. Una clase DownloadManager y una clase DownloadThread. El concepto obvio de OOP aquí es la composición. Sin embargo, la composición no necesariamente significa anidar, ¿verdad?¿Hay algún beneficio en definir una clase dentro de otra clase en Python?

tengo código que se ve algo como esto:

class DownloadThread: 
    def foo(self): 
     pass 

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

Pero ahora me pregunto si hay una situación en la anidación sería mejor. Algo como:

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

Respuesta

97

Es posible que desee hacer esto cuando la clase "interna" es una única vez, que nunca se utilizará fuera de la definición de la clase externa. Por ejemplo, para utilizar una metaclase, a veces es útil hacer

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

en lugar de definir una metaclase separado, si usted está utilizando solamente una vez.

La única otra vez que he utilizado clases anidadas como esa, se utiliza la clase externa sólo como un espacio de nombres para agrupar un montón de clases estrechamente relacionadas entre sí:

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

    class cls2(object): 
     ... 

Luego de otro módulo, se puede Importar grupo y referirse a estos como Group.cls1, Group.cls2 etc. Sin embargo, uno podría argumentar que puede lograr exactamente lo mismo (quizás de una manera menos confusa) mediante el uso de un módulo.

+9

Yo-argumentaría que en el segundo caso, usted -definitivamente- estaría mejor servido usando un módulo o paquete, que están diseñados para ser espacios de nombres. –

+3

Esta es una respuesta fantástica. Simple, al grano, y menciona el método alternativo de usar módulos. +1 – CornSmith

+5

Solo para el registro, para aquellos que obstinadamente se niegan o no pueden organizar su código en un paquete jerárquico y módulos adecuados, usar clases como un espacio de nombres a veces puede ser mejor que no usar nada. –

1

No, composición no significa anidamiento. Tendría sentido tener una clase anidada si desea ocultarla más en el espacio de nombres de la clase externa.

De todos modos, no veo ningún uso práctico para anidar en su caso. Haría que el código fuera más difícil de leer (entender) y también aumentaría la sangría que haría las líneas más cortas y más propensas a la división.

16

No conozco Python, pero su pregunta parece muy general. Ignorarme si es específico de Python.

Class nesting tiene que ver con el alcance. Si crees que una clase solo tendrá sentido en el contexto de otra, entonces la primera es probablemente una buena candidata para convertirse en una clase anidada.

Es un patrón común que hace clases auxiliares como clases privadas anidadas.

+6

Solo para tener en cuenta para el registro, el concepto de clases "privadas" no se aplica tanto en Python, pero un ámbito de uso implícito aún se aplica definitivamente. –

4

Podría estar utilizando una clase como generador de clases. Al igual que (en algunos fuera del código manguito :)

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

me siento como cuando necesita esta funcionalidad será muy claro para usted. Si no necesita hacer algo similar, probablemente no sea un buen caso de uso.

5

Realmente no hay ningún beneficio al hacer esto, excepto si se trata de metaclases.

la clase: suite realmente no es lo que crees que es. Es un alcance extraño, y hace cosas extrañas. ¡Realmente ni siquiera hace una clase! Es solo una forma de recopilar algunas variables: el nombre de la clase, las bases, un pequeño diccionario de atributos y una metaclase.

El nombre, el diccionario y las bases se pasan a la función que es la metaclase, y luego se asigna a la variable 'nombre' en el alcance donde estaba la clase: suite.

Lo que puede ganar jugando con metaclases, y de hecho anidando clases dentro de sus clases estándar, es más difícil de leer código, código más difícil de entender y errores extraños que son terriblemente difíciles de entender sin estar íntimamente familiarizado con por qué el alcance de 'clase' es completamente diferente a cualquier otro alcance de Python.

+3

No estoy de acuerdo: Clases de excepciones de anidamiento es muy útil, porque los usuarios de su clase pueden verificar sus excepciones personalizadas sin tener que realizar importaciones desordenadas. P.ej. '' excepto myInstanceObj.CustomError, e: '' – RobM

+0

Evil, antipattern, codesmell. -1 – Jerub

+2

@Jerub, ¿por qué es tan malo? –

Cuestiones relacionadas