¿Cuál es una buena forma de ordenar métodos en una clase de Python?

86

Quiero ordenar métodos en una clase de Python pero no sé cuál es el orden correcto.

Cuando extraigo métodos en Eclipse con PyDev, Eclipse coloca el método extraído encima del método modificado. Pero esto coloca los detalles de nivel inferior antes que los detalles de nivel superior. Según el tío Bob, debería hacer lo contrario para que mi código se lea como los titulares de un periódico. Cuando programo Java, simplemente sigo sus consejos.

¿Cuál es la mejor práctica para Python?

pez zeta
fuente
8
No existe una buena práctica. Haga lo que tenga más sentido: lo importante cerca de la parte superior es una buena idea, y la coherencia es generalmente algo bueno. PEP-8 no menciona esto, y si estuviera escrito en piedra, ahí es donde estaría.
Gareth Latty
4
E incluso PEP8 no siempre está escrito en piedra.
Ignacio Vazquez-Abrams
1
Normalmente lo hago por grupo en la funcionalidad (obtener, configurar, etc.)
CppLearner
Es importante tener en cuenta que el orden de las funciones de método puede ser arbitrario, porque una declaración de clase solo define sus funciones de método, no las invoca . Esto permite que el código fuente de las rutinas del método de clase utilice con éxito las funciones del método que se definirán más adelante en la lista.
DragonLord

Respuestas:

64

Como han señalado otros, no existe una forma correcta de ordenar sus métodos. Quizás una sugerencia de PEP sería útil, pero de todos modos. Permítame intentar abordar su pregunta de la manera más objetiva posible.

  • Interfaces primero: los métodos públicos y las funciones mágicas de Python definen la interfaz de la clase. La mayoría de las veces, usted y otros desarrolladores desean utilizar una clase en lugar de cambiarla. Por lo tanto, estarán interesados ​​en la interfaz de esa clase. Ponerlo en primer lugar en el código fuente evita desplazarse por los detalles de implementación que no le interesan.

  • Propiedades, métodos mágicos , métodos públicos: es difícil definir el mejor orden entre esos tres, que son parte de la interfaz de la clase. Como dice @EthanFurman, es más importante seguir con un sistema para todo el proyecto. En general, la gente espera __init__()la mejor primera función en la clase, así que sigo con los otros métodos mágicos que se encuentran a continuación.

  • Orden de lectura: Básicamente, hay dos formas de contar una historia: de abajo hacia arriba o de arriba hacia abajo. Al poner las funciones de alto nivel en primer lugar, un desarrollador puede obtener una comprensión aproximada de la clase leyendo las primeras líneas. De lo contrario, uno tendría que leer toda la clase para comprender la clase y la mayoría de los desarrolladores no tienen tiempo para eso. Como regla general, coloque los métodos por encima de todos los métodos llamados desde su cuerpo.

  • Métodos de clase y métodos estáticos: por lo general, esto está implícito en el orden de lectura explicado anteriormente. Los métodos normales pueden llamar a todos los métodos tiempos y, por lo tanto, vienen primero. Los métodos de clase solo pueden llamar a métodos de clase y métodos estáticos y vienen a continuación. Los métodos estáticos no pueden llamar a otros métodos de la clase y son los últimos.

Espero que esto ayude. Por cierto, la mayoría de estas reglas no son específicas de Python. No conozco un lenguaje que imponga el orden de los métodos, pero si es así, sería bastante interesante y por favor comente.

danijar
fuente
1
Por lo general, un idioma no obliga a ordenar. Pero algunos lenguajes tienen convenciones comunes. Por ejemplo, C # StyleCop tiene reglas de orden estrictas. Para Java, consulte stackoverflow.com/questions/4668218 , etc.
xmedeko
1
métodos de clase: estos se usan a menudo como constructores y luego suelen llamar __init__explícitamente (en combinación con __new__) o implícitamente (a través del constructor predeterminado), por lo que sería una razón para colocarlos junto con __init__. (Aunque nunca los había visto colocados antes __init__ )
oulenz
13

No hay un orden correcto. Elija un sistema y apéguese a él. El que yo uso es:

class SomeClass(object):
    def __magic_methods__(self):
        "magic methods first, usually in alphabetical order"
    def _private_method(self):
        "worker methods next, also in alpha order"
    def a_method(self):
        "then normal methods, also in alpha order"
Ethan Furman
fuente
2
¿Cuál es su preferencia por los métodos estáticos, las variables de clase y los métodos decorados con @property?
John Mee
@JohnMee: variables de clase que puse antes que cualquier otra cosa; mis plegables cueros método, el @staticmethod, @classmethod, @property, y cualesquiera otras @decoratorlíneas así que utilizo el tipo del método para determinar a dónde va (con la excepción de que las propiedades tienden a ir entre _private_methodsy normal_methods).
Ethan Furman
Entonces, si el orden básicamente va de métodos "mágicos" muy privados a métodos privados a normales, ¿eso significa que @classmethods viene después ( @classmethod def a_class_method(cls)) y luego @staticmethods ( @staticmethod def a_static_method())? Al menos esa es la política tal como la entiendo ... (sin que mi IDE doble nada porque no me gusta)
Kawu
2

Hago algo similar a @Ethan que vi en el código fuente de Django, donde la principal diferencia es un gran bloque de comentarios "###########" para delimitar las áreas. Por ejemplo,

class SomeClass(object):
    #################
    # Magic Methods #
    #################
    def __magic_methods__(self):
        "magic methods first"

    ##################
    # Public Methods #
    ##################
    def a_method(self):
        "then normal methods, in order of importance"

    ###################
    # Private Methods #
    ###################
    def _private_method(self):
        "then worker methods, grouped by importance or related function"

Obviamente, esto es menos útil para clases más pequeñas.

Matt Luongo
fuente
19
Pero puedo ver que son mágicos, públicos o privados. Yo mismo no me gustan activamente esos bloques de comentarios; Puedo mirar el código doblado si quiero ver una lista de todos ellos. Tener un comentario sobre un bloque particular de métodos relacionados con la funcionalidad es algo que haría, pero para este tipo de comentario, eso es lo que me dicen los nombres de los métodos.
Chris Morgan
Nuevamente, solo hago esto para clases más grandes. Encuentro que es fácil confundir métodos mágicos con métodos semiprivados ( ) y de nombres mutilados (_ ).
Matt Luongo
Estaba a mitad de edición quitando los ####bloques feos cuando me di cuenta de que los pondrías allí a propósito. Sin embargo, estoy de acuerdo con el pedido , que es de lo que trata esta pregunta. Recomendaría eliminar el ####de este ejemplo, ya que no pertenece al alcance de la pregunta y su ejemplo es de una clase pequeña, por lo que no usaría de ####todos modos. :-)
Mateen Ulhaq
1
@MateenUlhaq, consulte la segunda y quinta pautas que se muestran en la pantalla de edición: "aclarar el significado sin cambiarlo" y " respetar siempre al autor original". (Tenga en cuenta que estos están destinados a ser aplicados incondicionalmente, sin respetar la propia opinión del editor). El único objetivo de esta respuesta era mostrar esos desagradables bloques de comentarios; sin ellos, dice exactamente lo mismo que la respuesta de Ethan y no tiene sentido que esté aquí. Incluso reconoció que los bloques estaban allí " a propósito ". Sabiendo esto, ¿por qué iría y los eliminaría?
hola
1
@MIWright Lo pensé fuera del alcance de la pregunta. Como puede ver, rev2 todavía contiene material que responde a la pregunta de manera diferente a la de Ethan, con un orden diferente (¡y suborden!). Sin embargo, retrocedió.
Mateen Ulhaq