¿Usas el patrón get / set (en Python)?

82

Usar get / set parece ser una práctica común en Java (por varias razones), pero casi no veo código Python que use esto.

¿Por qué usa o evita los métodos get / set en Python?

Roger Pate
fuente
Grandes respuestas de todos. Es cierto que esta pregunta es una rama de esta stackoverflow.com/questions/1022970/… sin embargo, parece que fui atacado por una horda de personas que lo miraron desde una perspectiva de palabra "J". Gracias de nuevo por restaurar mi fe en la cordura ...
Avery Payne
1
El contexto es importante, y aquí Python y Java son simplemente diferentes. (Sin embargo, eliminé Python del título porque usamos etiquetas para eso en SO.;)

Respuestas:

59

Enlace genial: Python no es Java :)

En Java, debe usar getters y setters porque el uso de campos públicos no le da la oportunidad de volver atrás y cambiar de opinión más adelante para usar getters y setters. Por lo tanto, en Java, también podría deshacerse de la tarea desde el principio. En Python, esto es una tontería, porque puede comenzar con un atributo normal y cambiar de opinión en cualquier momento, sin afectar a ningún cliente de la clase. Por lo tanto, no escriba getters y setters.

mgv
fuente
3
además, los setters / getters agregan costo de rendimiento, especialmente en Python.
Nick Dandoulakis
4
Esto supone una carga adicional para el diseñador de la clase, ya que las variables de instancia se convierten implícitamente en parte de la API pública de la clase. Al diseñar una clase, piense explícitamente en las variables de instancia a las que desea acceder externamente frente a aquellas que en realidad son solo parte de la implementación de su clase. Prefije las implementaciones internas con un '_' inicial. Esta es la señal de advertencia de Python de que si la implementación cambia, esta variable también podría cambiar o incluso desaparecer por completo. De lo contrario, encontrará que el conocimiento de implementación se escapa de su clase, lo que dificulta el cambio más adelante.
PaulMcG
8
@Nick D: No creo que los descriptores de acceso sean el lugar adecuado para realizar optimizaciones de velocidad en Python.
wRAR
1
@Nick D: Quiero decir, es un lenguaje interpretado que fomenta la legibilidad, no el rendimiento, por lo que habrá mejores lugares para las optimizaciones en un programa.
wRAR
2
@ Pablo: Es no un atributo interno a menos que se nombra con uno o dos de subrayado iniciales (con la primera forma generalmente preferida ya que esta última hace inusual nombre mangling de Python). Si no desea escribir documentos y este problema le molesta, simplemente use _name por defecto para todos los atributos de instancia.
113

En Python, puede acceder al atributo directamente porque es público:

class MyClass:

    def __init__(self):
        self.my_attribute = 0  

my_object = MyClass()
my_object.my_attribute = 1 # etc.

Si desea hacer algo sobre el acceso o la mutación del atributo, puede usar las propiedades :

class MyClass:

    def __init__(self):
        self._my_attribute = 0

    @property
    def my_attribute(self):
        # Do something if you want
        return self._my_attribute

    @my_attribute.setter
    def my_attribute(self, value):
        # Do something if you want
        self._my_attribute = value

Fundamentalmente, el código del cliente sigue siendo el mismo.

blokeley
fuente
30

Esto es lo que dice Guido van Rossum sobre eso en Masterminds of Programming

¿Qué quieres decir con "luchar contra el idioma"?

Guido: Eso generalmente significa que están tratando de continuar con sus hábitos que funcionaron bien con un idioma diferente.

[...] La gente convertirá todo en una clase y convertirá cada acceso en un método de acceso,
donde eso no es realmente una cosa inteligente en Python; tendrá un código más detallado que es
más difícil de depurar y se ejecuta mucho más lento. ¿Conoce la expresión "Puede escribir FORTRAN en cualquier idioma?" También puede escribir Java en cualquier idioma.

Nick Dandoulakis
fuente
14

No, no es pitónico. La forma generalmente aceptada es usar atributos de datos normales y reemplazar los que necesitan una lógica get / set más compleja con propiedades.

Max Shawabkeh
fuente
13
+1: "Todos somos adultos aquí". El código es visible. "private" y "getter / setter" no crean ningún valor cuando se puede ver todo el código.
S.Lott
7

La respuesta corta a su pregunta es no, debe usar propiedades cuando sea necesario. Ryan Tamyoko proporciona la respuesta larga en su artículo Getters / Setters / Fuxors

El valor básico que se debe extraer de todo esto es que desea esforzarse por asegurarse de que cada línea de código tenga algún valor o significado para el programador. Los lenguajes de programación son para humanos, no para máquinas. Si tiene un código que parece que no hace nada útil, es difícil de leer o parece tedioso, entonces es muy probable que Python tenga alguna característica de lenguaje que le permita eliminarlo.

Shane C. Mason
fuente
5

Tu observación es correcta. Este no es un estilo normal de programación en Python. Los atributos son todos públicos, por lo que simplemente acceda (obtenga, establezca, elimine) como lo haría con los atributos de cualquier objeto que los tenga (no solo clases o instancias). Es fácil saber cuándo los programadores de Java aprenden Python porque su código Python se parece a Java usando la sintaxis de Python.

Definitivamente estoy de acuerdo con todos los carteles anteriores, especialmente el enlace de @ Maximiliano al famoso artículo de Phillip y la sugerencia de @ Max de que cualquier cosa más compleja que la forma estándar de configurar (y obtener) atributos de clase e instancia es usar Propiedades (o Descriptores para generalizar aún más) para personalizar la obtención y configuración de atributos. (Esto incluye poder agregar sus propias versiones personalizadas de privado, protegido, amigo o cualquier política que desee si desea algo que no sea público).

Como demostración interesante, en Core Python Programming (capítulo 13, sección 13.16), se me ocurrió un ejemplo de cómo usar descriptores para almacenar atributos en el disco en lugar de en la memoria. Sí, es una forma rara de almacenamiento persistente, pero hace que muestran un ejemplo de lo que es posible!

Aquí hay otra publicación relacionada que también puede resultarle útil: Python: múltiples propiedades, un setter / getter

wescpy
fuente
0

Había venido aquí por esa respuesta (lamentablemente no pude). Pero encontré un trabajo en otro lugar. Este código a continuación podría ser una alternativa para get .
class get_var_lis: def __init__(self): pass def __call__(self): return [2,3,4] def __iter__(self): return iter([2,3,4]) some_other_var = get_var_lis
Esto es solo una solución . Al usar el concepto anterior, también podría construir fácilmente la metodología get / set en py.

Yunus
fuente
-10

Nuestro profesor mostró un ejemplo en clase que explica cuándo debemos usar las funciones de acceso.

class Woman(Human):
    def getAge(self):
        if self.age > 30:
            return super().getAge() - 10
        else:
            return super().getAge()
sjhstone
fuente
No le di los votos negativos, pero pensé que intervendría. El punto de la discusión es "¿por qué necesitamos get () / set () para acceder a las propiedades directamente en Python". En Java, hay características del lenguaje ... que lo hacen deseable. En Python, no tanto.
Avery Payne
7
Además de no responder realmente a la pregunta, el ejemplo utilizado en esta respuesta es ofensivo. La afirmación de que su maestro lo utilizó no justifica su sexismo.
Touzen
Dudo que esto muestre sexismo, simplemente tu ingenuidad. En la generación de mi abuela, muchas mujeres bromeaban diciendo que su edad era algunos años menor de lo que realmente era. Además, no tiene nada que ver con la respuesta de todos modos.
Johan Snowgoose