operaciones funciones example con python partial-classes

example - operaciones con funciones en python



¿Hay algún Python equivalente a las clases parciales? (8)

Anteriormente he jugado con algo similar. Mi caso de uso era una jerarquía de clases de nodos en un árbol sintáctico abstracto, y luego quise poner todas las funciones de impresión, por ejemplo, bastante bonitas en un archivo separado de prettyprint.py pero todavía las tengo como métodos en las clases.

Una cosa que probé fue usar un decorador que pone la función decorada como un atributo en una clase específica. En mi caso, esto significaría que prettyprint.py contiene un montón de def prettyprint(self) decorado con diferentes @inclass(...)

Un problema con esto es que uno debe asegurarse de que los archivos secundarios siempre se importen y que dependan de la clase principal, lo que genera una dependencia circular, que puede ser complicada.

def inclass(kls): """ Decorator that adds the decorated function as a method in specified class """ def _(func): setattr(kls,func.__name__, func) return func return _ ## exampe usage class C: def __init__(self, d): self.d = d # this would be in a separate file. @inclass(C) def meth(self, a): """Some method""" print "attribute: %s - argument: %s" % (self.d, a) i = C(10) print i.meth.__doc__ i.meth(20)

Usando clases de estilo "nuevo" (estoy en Python 3.2) ¿hay alguna manera de dividir una clase en varios archivos? Tengo una clase grande (que en realidad debería ser una sola clase desde una perspectiva de diseño orientada a objetos, considerando el acoplamiento, etc.), pero sería bueno dividir algunos archivos solo para facilitar la edición de la clase.


En primer lugar, no veo cómo dividir la clase en múltiples archivos facilita la edición. Un IDE decente debería ser capaz de encontrar cualquier método fácilmente ya sea en un archivo o en un archivo múltiple; si no está usando un IDE decente, dividir la clase significa que el mantenedor tiene que adivinar en qué archivo se encuentra un método dado, lo que suena más difícil que más fácil.

Más fundamentalmente, esta clase, tan grande que desea una función de idioma especial solo para soportar su peso, suena fundamentalmente rota. ¿Cuántas líneas de código estamos hablando? Casi con certeza, sería una mejor idea hacer uno de:

  • Refactorizar código duplicado en menos primitivas más generales
  • Defina una clase base y extiéndala con subclases como sugiere Karoly Horvath en los comentarios (esto es lo más parecido a las ''clases parciales'' que está pidiendo y que aprobaría)
  • Defina unas pocas clases separadas para encapsular diferentes partes de la funcionalidad de esta clase, y componga esta clase de instancias de aquellas más pequeñas.

Las definiciones de clase que contienen cientos de líneas sí ocurren "en la naturaleza" (he visto algunas en frameworks populares basados ​​en Python), pero creo que si reflexionas sobre lo que están haciendo los métodos, será posible reducir la longitud de la mayoría de las clases a un punto manejable. Algunos ejemplos:

  • Busque lugares donde, en su mayoría, el mismo código aparece más de una vez. Divide ese código en su propio método y llámalo desde cada lugar con argumentos.
  • Los métodos "privados" que no usan ninguno del estado del objeto se pueden sacar de la clase como funciones independientes.
  • Los métodos que deben invocarse solo bajo ciertas condiciones pueden indicar la necesidad de ubicar esos métodos en una subclase.

Para abordar directamente su pregunta, es posible dividir la definición de una clase. Una forma es "aplicar parche" a la clase definiéndola y luego añadiéndole funciones externas como métodos. Otra es utilizar la función de type incorporada para crear la clase "a mano", proporcionando su nombre, cualquier clase base y sus métodos y atributos en un diccionario. Pero no recomiendo hacer esto solo porque la definición sería larga de lo contrario. Ese tipo de curación es peor que la enfermedad en mi opinión.


Me encontré con la misma situación: quiero transferir mi clase a 2 archivos. el motivo es que: deseo la parte 1 para el diseño de la GUI, solo el diseño y otro archivo conservan todas las funciones. como la clase parcial de c #. uno para XAML y otro para funciones.


No lo he usado, pero este paquete llamó reclamos parciales para agregar soporte para clases parciales.

Parece que hay algunas otras formas en que puede implementar esto usted también.

Podrías implementar partes separadas de la clase como mixins en archivos separados, luego importarlos a todos en alguna parte y subclasificarlos.

Alternativamente, puede implementar cada uno de los métodos de su clase en algún lugar, luego, en un archivo central, importarlos y asignarlos como atributos en una clase, para crear el objeto completo. Al igual que:

a.py:

def AFunc( self, something ): # Do something pass

b.py:

def BFunc( self, something ): # Do something else pass

c.py:

import a, b class C: AFunc = a.AFunc BFunc = b.BFunc

Incluso podría llegar a automatizar este proceso si realmente lo desea: recorra todas las funciones provistas por los módulos a y b y luego agréguelos como atributos en C Aunque eso podría ser una exageración total.

Puede haber otras (posiblemente mejores) formas de hacerlo, pero esos son los 2 que aparecieron en la mente.


Primero, me gustaría decir que algo así de complicado, probablemente no sea una buena idea solo para facilitar la búsqueda de su lugar en la clase; sería mejor agregar comentarios, resaltar secciones, etc. Sin embargo, veo dos maneras en que podría hacer esto. :

  1. Escriba la clase en varios archivos, luego léelos como texto, conéctelos y exec la cadena resultante.

  2. Cree una clase por separado en cada archivo, luego los heredará todos en una clase maestra como mixins. Sin embargo, si está subclasificando otra clase, esto podría generar problemas de MRO. Podrías evitar esto creando una metaclase para tu clase maestra que resuelve manualmente el MRO, pero esto podría ser complicado.

La más fácil sería la primera opción.


Puedes hacer esto con decoradores de esta manera:

class Car(object): def start(self): print ''Car has started'' def extends(klass): def decorator(func): setattr(klass, func.__name__, func) return func return decorator #this can go in a different module/file @extends(Car) def do_start(self): self.start() #so can this car = Car() car.do_start() #=> Car has started


Si su problema es solo trabajar con una clase grande en un editor, la primera solución que realmente buscaría es una mejor manera de analizar el problema. La segunda solución sería un mejor editor, preferiblemente uno con plegado de código.

Dicho esto, hay un par de maneras en que puedes dividir una clase en varios archivos. Python le permite usar una carpeta como módulo colocando una __init__.py en ella, que luego puede importar cosas desde otros archivos. Usaremos esta capacidad en cada solución. Primero bigclass una carpeta llamada, digamos, bigclass .

  1. En la carpeta, coloque los diversos archivos .py que eventualmente formarán parte de su clase. Cada uno debe contener funciones y definiciones de variables para la clase eventual, no para las clases. En __init__.py en la misma carpeta, escribe lo siguiente para unirlas todas juntas.

    class Bigclass(object): from classdef1 import foo, bar, baz, quux from classdef2 import thing1, thing2 from classdef3 import magic, moremagic # unfortunately, "from classdefn import *" is an error or warning num = 42 # add more members here if you like

    Esto tiene la ventaja de que terminas con una sola clase derivada directamente del object , que se verá bien en tus gráficos de herencia.

  2. Puede usar herencia múltiple para combinar las diversas partes de su clase. En sus módulos individuales, escribiría una definición de clase para Bigclass con partes de la clase. Luego en tu __init__.py escribe:

    import classdef1, classdef2, classdef3 class Bigclass(classdef1.Bigclass, classdef2.Bigclass, classdef3.Bigclass): num = 42 # add more members if desired

  3. Si la herencia múltiple se convierte en un problema, puede usar la herencia individual: simplemente haga que cada clase herede de otra en forma de cadena. Suponiendo que no define nada en más de una clase, el orden no importa. Por ejemplo, classdef2.py sería como:

    import classdef1 class Bigclass(classdef1.Bigclass): # more member defs here

    classdef3 importaría Bigclass de classdef2 y lo agregaría, y así sucesivamente. Tu __init__.py solo importaría el último:

    from classdef42 import Bigclass

En general, preferiría el n. ° 1 porque es más explícito sobre qué miembros está importando de qué archivos, pero cualquiera de estas soluciones podría funcionar para usted.

Para usar la clase en cualquiera de estos escenarios, simplemente puede importarla, usando el nombre de la carpeta como nombre del módulo: from bigclass import Bigclass