Categorías
Python

Introducción a la programación orientada a objetos (POO) en Python

 

Tabla de Contenidos

  • instancia, la clase y métodos estáticos – Un OverviewInstance de MethodsClass Métodos MethodsStatic
  • Métodos de instancia
  • Métodos de clase
  • métodos estáticos
  • Let verlos en acción! Las fábricas
  • deliciosa pizza con @classmethod
  • cuándo utilizar métodos estáticos
  • Conclusiones clave
  • Métodos de instancia
  • Métodos de clase

  • métodos estáticos

Mira ahora Este tutorial tiene un video relacionado con el curso creado por el real equipo de Python. Verlo junto con el tutorial escrito para profundizar su comprensión: Tipos programación orientada a objetos en Python Método: @classmethod vs vs @staticmethod Instancia Métodos

En este tutorial voy a ayudar a desmitificar lo que hay detrás de los métodos de clase métodos estáticos , , y los métodos regulares de instancia .

Si desarrolla una comprensión intuitiva de sus diferencias usted será capaz de escribir Python orientado a objetos que se comunica su intención más clara y será más fácil de mantener en el largo plazo. Bono

gratuito: Haga clic aquí para obtener acceso a una hoja de programación orientada a objetos Python libre de trucos que le apunta a los mejores tutoriales, videos y libros para aprender más acerca de la programación orientada a objetos con Python.

instancia, la clase y métodos estáticos – Una visión general

Vamos a empezar por escribir una (3 Python) clase que contiene ejemplos simples para los tres tipos de método:

class MyClass:
def method(self):
return 'instance method called', self

@classmethod
def classmethod(cls):
return 'class method called', cls

@staticmethod
def staticmethod():
return 'static method called'

NOTA: Para Python 2 usuarios: La @staticmethod y decoradores @classmethod están disponibles a partir de Python 2.4 y este ejemplo funcionará como se muestran. En lugar de utilizar una clase MiClase llano: declaración puede optar por declarar una clase de nuevo estilo que hereda de objeto con la clase MiClase (objeto): sintaxis. Aparte de eso ya está bueno para ir.

Métodos de instancia

El primer método en MyClass, llamado método, es un método regular ejemplo . Ese es el tipo de método, sin lujos básicos que va a utilizar la mayor parte del tiempo. Se puede ver el método toma un parámetro, uno mismo, lo que apunta a una instancia de MyClass cuando se llama al método (pero por supuesto método de instancia s puede aceptar más de un parámetro).

A través del parámetro de uno mismo, los métodos de instancia puede acceder libremente a los atributos y otros métodos en el mismo objeto. Esto les da una gran cantidad de energía cuando se trata de modificar el estado de un objeto.

No sólo pueden modificar el estado del objeto, los métodos de instancia también pueden acceder a la clase en sí a través del atributo self .__ class__. Este métodos de instancia medios también pueden modificar el estado del clase.

Métodos de clase

que vamos a comparar con el segundo método, MyClass.classmethod. Marqué este método con un decorador @classmethod a marcarlo como un método de clase .

En lugar de aceptar un parámetro de uno mismo, métodos de clase, tómese cls parámetro que apunta a la clase y no el objeto de instancia-cuando el método se llama.

Debido a que el método de clase sólo tiene acceso a este argumento cls, no puede modificar el estado instancia de objeto. Para ello sería necesario el acceso a uno mismo. Sin embargo, los métodos de clase todavía puede modificar el estado de clase que se aplica a todas las instancias de la clase.

métodos estáticos

El tercer método, MyClass.staticmethod fue marcado con un decorador @staticmethod a la bandera como un método estática .

Este tipo de método toma ni un auto ni un parámetro cls (pero por supuesto que es libre de aceptar un número arbitrario de otros parámetros).

Por lo tanto un método estático y no las puede modificar el estado del objeto ni Estado de clase. Los métodos estáticos están restringidos en qué datos pueden acceder – y son principalmente una forma de espacio de nombres a sus métodos.

Vamos a verlos en acción!

Sé que esta discusión ha sido con bastante teórica a este punto. Y yo creo que es importante que desarrollar una comprensión intuitiva de cómo estos tipos de métodos difieren en la práctica. Vamos a repasar algunos ejemplos concretos ahora.

vamos a echar un vistazo a cómo se comportan estos métodos en acción cuando los llamamos. Vamos a empezar por la creación de una instancia de la clase y luego llamar a los tres métodos diferentes sobre el mismo.

MiClase se creó de tal manera que la aplicación de cada método devuelve una tupla que contiene la información para realizar la trazabilidad de lo que está pasando – y que partes de la clase u objeto el acceso método de lata.

Esto es lo que sucede cuando llamamos a un método de instancia :

>>> obj = MyClass()
>>> obj.method()
('instance method called', )

Esta confirmado que el método (el método de instancia) tiene acceso a la instancia del objeto (impreso como ) a través del argumento de uno mismo.

Cuando se llama al método, Python sustituye el argumento de uno mismo con el objeto de instancia, obj. Podríamos ignorar el azúcar sintáctico de la sintaxis con puntos de atención continuada (obj.method ()) y pase el objeto de instancia manualmente para obtener el mismo resultado:

>>> MyClass.method(obj)
('instance method called', )

se puede adivinar lo que sucedería si se trató de llamar al método sin en primer lugar la creación de una instancia?

Por cierto, los métodos de instancia también se puede acceder a la clase en sí a través del atributo self .__ class__. Esto hace que los métodos de instancia poderosa en términos de restricciones de acceso – que pueden modificar el estado de la instancia de objeto y en la propia clase . try de

dejar salir el método de clase siguiente:

>>> obj.classmethod()
('class method called', )

classmethod Calling () nos mostró que no tiene acceso a la objeto, pero sólo en la objeto, que representa la clase en sí ( todo en Python es un objeto, incluso clases en sí).

Note como Python pasa automáticamente a la clase como el primer argumento de la función cuando llamamos MyClass.classmethod (). Llamar a un método en Python a través de la Sintaxis con puntos desencadenantes este comportamiento. El parámetro auto sobre los métodos de instancia funciona de la misma manera.

Tenga en cuenta que el nombramiento de estos parámetros sí mismo y CLS es sólo una convención. Se podía nombrar tan fácilmente the_object y the_class y obtener el mismo resultado. Lo único que importa es que están posicionados en primer lugar en la lista de parámetros del método.

momento de llamar al método estático ahora:

>>> obj.staticmethod()
'static method called'

usted vio cómo llamamos métodoestático () en el objeto y fuimos capaces de hacerlo con éxito? Algunos desarrolladores se sorprenden cuando se enteran de que es posible llamar a un método estático en una instancia de objeto.

Detrás de las escenas de Python simplemente hace cumplir las restricciones de acceso al no pasar en el auto o el argumento cls cuando un método estático se llama usando la sintaxis con punto.

Esto confirma que los métodos estáticos pueden acceder ni el estado de la instancia de objeto ni el Estado de clase. Funcionan como funciones regulares, sino que pertenecen a (y de todos los casos) de espacio de nombres de la clase.

Ahora, vamos a echar un vistazo a lo que sucede cuando se intenta llamar a estos métodos en la clase en sí – sin crear una instancia de objeto de antemano:

>>> MyClass.classmethod()
('class method called', )

>>> MyClass.staticmethod()
'static method called'

>>> MyClass.method()
TypeError: unbound method method() must
be called with MyClass instance as first
argument (got nothing instead)

Hemos sido capaces de classmethod llamada () y métodoestático () muy bien, pero el intento para llamar al método método de instancia () falló con un TypeError.

Y esto es de esperar – esta vez no creamos una instancia de objeto y tratamos de llamar a una función ejemplo directamente en el propio plan de clase. Esto significa que no hay manera para Python para poblar el argumento de uno mismo y, por tanto, falla la llamada.

Esto debería hacer la distinción entre estos tres tipos de métodos un poco más clara. Pero no voy a dejar las cosas así. En las siguientes dos secciones voy a ir más de dos ejemplos un poco más realistas para cuándo utilizar estos tipos de métodos especiales.

basaré mis ejemplos en torno a este escueto clase de pizza:

class Pizza:
def __init__(self, ingredients):
self.ingredients = ingredients

def __repr__(self):
return f'Pizza({self.ingredients!r})'

>>> Pizza(['cheese', 'tomatoes'])
Pizza(['cheese', 'tomatoes'])

Nota: Este ejemplo de código y los más avanzados en el uso tutorial de Python 3.6 f-cuerdas para construir la cadena devuelta por __repr__. En Python 2 y 3 versiones de Python 3.6 antes de que tendría que utilizar una cadena de expresión de formato diferente, por ejemplo: fábricas

def __repr__(self):
return 'Pizza(%r)' % self.ingredients

deliciosa pizza con @classmethod

Si ha tenido cualquier tipo de exposición a la pizza en el mundo real se le saben que hay muchas variaciones deliciosas disponibles:

Pizza(['mozzarella', 'tomatoes'])
Pizza(['mozzarella', 'tomatoes', 'ham', 'mushrooms'])
Pizza(['mozzarella'] * 4)

Los italianos descubierto la hace siglos sus pizzas taxonomía, y así estos deliciosos tipos de pizzas, todos tienen sus propios nombres. Nos haría bien en tomar ventaja de eso y dar a los usuarios de nuestra clase pizza una mejor interfaz para crear la pizza objetos que se les antoja.

Un agradable y limpio manera de hacerlo es mediante el uso de métodos de clase como funciones de fábrica para los diferentes tipos de pizzas que puede crear:

class Pizza:
def __init__(self, ingredients):
self.ingredients = ingredients

def __repr__(self):
return f'Pizza({self.ingredients!r})'

@classmethod
def margherita(cls):
return cls(['mozzarella', 'tomatoes'])

@classmethod
def prosciutto(cls):
return cls(['mozzarella', 'tomatoes', 'ham'])

Nota cómo estoy usando el argumento cls en los métodos de fábrica Margherita y jamón en lugar de llamar la pizza constructor directamente.

Este es un truco que puede utilizar para seguir el No te repitas (DRY) principio. Si decidimos cambiar el nombre de esta clase en algún momento no vamos a tener que recordar actualizar el nombre del constructor en todas las funciones de fábrica classmethod.

Ahora bien, ¿qué podemos hacer con estos métodos de fábrica? Vamos a probar:

>>> Pizza.margherita()
Pizza(['mozzarella', 'tomatoes'])

>>> Pizza.prosciutto()
Pizza(['mozzarella', 'tomatoes', 'ham'])

Como se puede ver, podemos utilizar las funciones de fábrica para crear nuevos objetos de pizza que se configuran la forma en que los queremos. Todos ellos utilizan el mismo constructor __init__ internamente y simplemente proporcionan un acceso directo para recordar todos los diversos ingredientes.

Otra manera de mirar este uso de métodos de clase es que le permiten definir constructores alternativos para sus clases.

Python sólo permite un método __init__ por clase. El uso de métodos de clase que es posible añadir tantos constructores alternativos, según sea necesario. Esto puede hacer que la interfaz para sus clases de auto-documentado (hasta cierto punto) y simplificar su uso.

cuándo utilizar métodos estáticos

Es un poco más difícil para llegar a un buen ejemplo de ello. Pero le dirá qué, voy a seguir estirando la analogía más delgado y más delgado de pizza … (mmm!)

Esto es lo que ocurrió:

import math

class Pizza:
def __init__(self, radius, ingredients):
self.radius = radius
self.ingredients = ingredients

def __repr__(self):
return (f'Pizza({self.radius!r}, '
f'{self.ingredients!r})')

def area(self):
return self.circle_area(self.radius)

@staticmethod
def circle_area(r):
return r ** 2 * math.pi

Ahora ¿qué puedo cambiar aquí? En primer lugar, he modificado el constructor y __repr__ para aceptar un argumento radio adicional. También

añadí una zona método de instancia () que calcula y devuelve el área de la pizza (esto también sería un candidato bueno para un @property – pero bueno, esto es sólo un ejemplo de juguete).

En lugar de calcular el área directamente en el área de (), utilizando la fórmula área del círculo bien conocido, I factorizado que a un circle_area separado () método estático.

Vamos a probarlo!

>>> p = Pizza(4, ['mozzarella', 'tomatoes'])
>>> p
Pizza(4, ['mozzarella', 'tomatoes'])
>>> p.area()
50.26548245743669
>>> Pizza.circle_area(4)
50.26548245743669

Claro, esto es un poco de un ejemplo simplista, pero servirá bien ayudar a explicar algunos de los beneficios que proporcionan los métodos estáticos.

Como hemos aprendido, los métodos estáticos no puede clase de acceso o el estado de la instancia debido a que no tome una cls o argumento de uno mismo. Esa es una gran limitación – pero también es una gran señal para demostrar que un método particular es independiente de todo lo demás a su alrededor.

En el ejemplo anterior, está claro que circle_area () no puede modificar la clase o la instancia de clase de ninguna manera. (Por supuesto, siempre se puede evitar que con una variable global, pero ese no es el punto aquí.)

Ahora, ¿por qué es tan útil?

Las marcas un método como un método estático no es sólo un indicio de que un método no modificará clase o instancia estado – esta restricción también se aplica por el tiempo de ejecución Python. Técnicas

como que le permiten comunicarse con claridad sobre partes de su arquitectura de alta calidad para que el nuevo trabajo de desarrollo se guía de forma natural a suceder dentro de estos límites establecidos. Por supuesto, sería bastante fácil de desafiar a estas restricciones. Pero en la práctica, a menudo ayuda a evitar modificaciones accidentales que van en contra del diseño original.

Dicho de otra manera, el uso de métodos estáticos y métodos de clase son formas de comunicarse desarrollador intención al tiempo que aplica suficiente que la intención de evitar la mayor parte de deslizamiento de los errores de la mente y los insectos que romperían el diseño.

aplicada con moderación y cuando tiene sentido, escribiendo algunos de sus métodos de esa manera puede proporcionar beneficios de mantenimiento y hacer que sea menos probable que otros desarrolladores utilizan sus clases de forma incorrecta. métodos

estáticas también tienen beneficios cuando se trata de escribir código de prueba.

Debido a que el método de circle_area () es completamente independiente del resto de la clase que es mucho más fácil de prueba.

Nosotros no tiene que preocuparse por la creación de una instancia de clase completa antes de que podamos probar el método en una unidad de prueba. Podemos simplemente el fuego inmediato como nos gustaría probar una función regular. Una vez más, esto hace más fácil el mantenimiento futuro. métodos

Conclusiones clave

  • instancia necesitan una instancia de clase y pueden acceder a la instancia a través del auto. métodos
  • clase no necesitan una instancia de clase. No pueden acceder a la instancia (auto) pero tienen acceso a través de la propia clase cls. métodos
  • estáticos no tienen acceso a CLS o auto. Funcionan como funciones regulares, sino que pertenecen al espacio de nombres de la clase.
  • estático y métodos de clase se comunican y (hasta cierto punto) hacer cumplir desarrollador intención sobre el diseño de clase. Esto puede tener beneficios de mantenimiento.

Mira ahora Este tutorial tiene un vídeo relacionado curso creado por el equipo del Real Python. Mira que junto con el tutorial escrito para profundizar su comprensión: Tipos programación orientada a objetos en Python Método: @classmethod vs vs @staticmethod Métodos de instancia

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *