programacion - ¿Hay algún beneficio en definir una clase dentro de otra clase en Python?
poo python 3 (6)
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?
Tengo un código que se ve así:
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 que anidar 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())
Es posible que desee hacer esto cuando la clase "interna" sea una única vez, que nunca se utilizará fuera de la definición de la clase externa. Por ejemplo, para usar una metaclase, a veces es útil hacerlo
class Foo(object):
class __metaclass__(type):
....
en lugar de definir una metaclase por separado, si solo la está utilizando una vez.
La única otra vez que utilicé clases anidadas como esa, utilicé la clase externa solo como un espacio de nombres para agrupar un grupo de clases estrechamente relacionadas entre sí:
class Group(object):
class cls1(object):
...
class cls2(object):
...
Luego, desde otro módulo, puede importar Group y referirse a éstos como Group.cls1, Group.cls2, etc. Sin embargo, se podría argumentar que puede lograr exactamente lo mismo (quizás de una manera menos confusa) mediante el uso de un módulo.
Hay otro uso para la clase anidada, cuando uno quiere construir clases heredadas cuyas funcionalidades mejoradas están encapsuladas en una clase anidada específica.
Mira este ejemplo:
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)
Tenga en cuenta que en el constructor de foo
, la línea self.a = self.bar()
construirá un foo.bar
cuando el objeto que se está construyendo es en realidad un objeto foo
, y un objeto foo2.bar
cuando el objeto que se está construyendo es en realidad un objeto foo2
.
Si la bar
clase se definiera fuera de la clase foo
, al igual que su versión heredada (que se llamaría bar2
por ejemplo), definir la nueva clase foo2
sería mucho más doloroso, porque el constuctor de foo2
necesitaría tener su primera línea reemplazada por self.a = bar2()
, lo que implica volver a escribir todo el constructor.
No conozco a Python, pero su pregunta parece muy general. Ignorarme si es específico de Python.
La anidación de clases 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 que las clases auxiliares sean clases privadas y anidadas.
No, la composición no significa anidar. 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.
Podrías estar usando una clase como generador de clases. Me gusta (en algunos fuera del código de 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''''''
Siento que cuando necesites esta funcionalidad, será muy claro para ti. Si no necesita hacer algo similar, probablemente no sea un buen caso de uso.
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é la ''clase'' el alcance es completamente diferente a cualquier otro ámbito de Python.