Bienvenido de nuevo a la lección cuatro en nuestro Python desde cero serie. Este tutorial asumirá un conocimiento previo de variables, tipos de datos, funciones y resultados de impresión. Si no está actualizado, revise los tres artículos anteriores de la serie para ponerse al día..
Hoy vamos a profundizar en el tema de Programación Orientada a Objetos (OOP). OOP es una forma muy poderosa de organizar su código, y una comprensión sólida de los conceptos que lo respaldan puede ayudarlo a aprovechar al máximo su codificación..
Python está diseñado principalmente como un lenguaje de programación orientado a objetos, pero lo que realmente significa "orientado a objetos"?
Hay una variedad de definiciones para el término, y puedes hablar durante horas, literalmente, tratando de explicar los complicados detalles, matices y diferencias en las implementaciones, pero trataré de ofrecer una descripción general rápida..
En términos generales, la programación orientada a objetos es el concepto de que, en programación, los objetos que estamos manipulando son más importantes que la lógica necesaria para manipular esos objetos. Tradicionalmente, un programa ha sido visto como una receta, un conjunto de instrucciones que sigue de principio a fin para completar una tarea. Eso todavía puede ser cierto, y para muchos programas simples, eso es todo lo que se requiere. Ese enfoque es a veces conocido como programación procesal..
OOP pone objetos en el centro del proceso..
Por otro lado, a medida que los programas se vuelven cada vez más complejos y complicados, la lógica necesaria para escribirlos de una manera puramente procesal se vuelve cada vez más retorcida y difícil de entender. A menudo los enfoques orientados a objetos pueden ayudar con eso.
Cuando hablamos de enfoques orientados a objetos, lo que hacemos es colocar los objetos en el centro del proceso, en lugar de simplemente usarlos como contenedores necesarios para obtener información como parte de nuestras instrucciones de procedimiento. Primero, definimos los objetos que queremos manipular y cómo se relacionan entre sí, y luego comenzamos a desarrollarlo con lógica para hacer que el programa realmente funcione..
Cuando hablo de 'objetos', puedo hablar de todo tipo de cosas. Un 'objeto' puede representar a una persona (como se define por propiedades como nombre, edad, dirección, etc.), o una compañía (como se define por cosas como el número de empleados, etc.), o incluso algo mucho más abstracto, como un botón en una interfaz de computadora.
En esta introducción, no vamos a cubrir todos los conceptos de este tema porque estaremos aquí toda la noche, pero al final del tutorial, espero que tenga una comprensión sólida de los principios que necesita para comenzar de inmediato con algunas técnicas simples orientadas a objetos en sus programas de Python. Aún mejor, estos conceptos son bastante similares en muchos entornos de programación. El conocimiento se transfiere de un idioma a otro bastante bien..
Anteriormente mencioné que lo primero que deberíamos hacer cuando optamos por un enfoque OOP es definir los objetos que vamos a utilizar. La forma en que lo hacemos es definir primero las propiedades que posee mediante una clase. Puedes pensar en una clase como una especie de plantilla; Una guía para la forma en que debe estructurarse un objeto. Cada objeto pertenece a una clase y hereda las propiedades de esa clase, pero actúa individualmente para los otros objetos de esa clase..
Un objeto a veces se conoce como una 'instancia' de una clase.
Como ejemplo simple, puede tener una clase llamada 'persona' con, digamos, una edad y una propiedad de nombre, y una instancia de esa clase (un objeto) sería una sola persona. Esa persona podría tener un nombre de? Andy? y una edad de 23 años, pero al mismo tiempo podrías tener otra persona perteneciente a la misma clase con el nombre de? Lucy? y una edad de 18.
Es difícil entender esto sin verlo en la práctica, así que vamos a poner en marcha un código real.
Para definir una clase, en la forma típica de Python simple, usamos la palabra 'clase', seguida del nombre de su nueva clase. Voy a hacer una nueva clase aquí, llamada 'mascota'. Usamos dos puntos después del nombre, y luego cualquier cosa contenida dentro de la definición de la clase se sangra. Sin embargo, con una clase, no hay paréntesis:
mascota de clase:
Así que ahora tenemos una clase, pero es bastante inútil sin nada en ella. Para empezar, vamos a darle un par de propiedades. Para hacer esto, simplemente defina algunas variables dentro de la clase. Voy a ir con la cantidad de pasos para comenzar. Como siempre, siempre debe nombrar sus variables para que sea fácil saber cuáles son. Seamos originales y llamémosle 'number_of_legs'. Necesitamos definir un valor o obtendremos un error. Usaré 0 aquí (no importa demasiado en este caso, ya que la cantidad de patas será específica para cada instancia de la clase: un pez no tiene la misma cantidad de patas que un perro o un pato, etc. - así que tendremos que cambiar ese valor para cada objeto de todos modos).
clase mascota: número_de_legs = 0
Una clase en sí misma no es algo que puedas manipular directamente; Primero, tenemos que crear una instancia de la clase para jugar. Podemos almacenar esa instancia en una variable. Fuera de la clase (sin sangría), hagamos una instancia de la clase y la almacenemos en la variable, 'doug'. Para crear una nueva instancia de una clase, simplemente escriba el nombre de la clase y luego un par de paréntesis. En este punto, no hay necesidad de preocuparse por los paréntesis, pero más adelante verá que están allí porque, como una función, hay una forma de pasar una variable para que la clase la use la primera vez que cree la instancia..
Una clase en sí misma no es algo que pueda manipular directamente.
class pet: number_of_legs = 0 doug = pet ()
Ahora que tenemos una instancia de una clase, ¿cómo accedemos y manipulamos sus propiedades? Para hacer referencia a una propiedad de un objeto, primero tenemos que decirle a Python de qué objeto (o qué instancia de una clase) estamos hablando, así que comenzaremos con 'doug'. Luego, vamos a escribir un punto para indicar que estamos haciendo referencia a algo que está contenido dentro de nuestra instancia de doug. Después del período, agregamos el nombre de nuestra variable. Si estamos accediendo a la number_of_legs
Variable, se verá así:
doug.number_of_legs
Podemos tratar eso ahora exactamente como lo haríamos con cualquier otra variable; aquí asumiré que doug es un perro, y le daremos a esa variable el valor de 4.
Para acceder a esta variable, la usaremos de nuevo exactamente como trataríamos cualquier otra variable, pero al usarla doug.number_of_legs
propiedad en lugar del nombre de variable normal. Pongamos una línea para imprimir cuántas patas tiene doug para poder demostrar que está funcionando como debería:
class pet: number_of_legs = 0 doug = pet () doug.number_of_legs = 4 print "Doug tiene% s piernas". % doug.number_of_legs
Si ejecuta el código anterior, verá que está impreso para nosotros. Definió nuestra clase 'mascota', creó una nueva instancia de esa clase y la almacenó en la variable 'doug', y luego, dentro de esa instancia, se le asigna el valor de 4 al number_of_legs
Variable que heredó de su clase..
Por lo que puede ver en ese ejemplo muy simplificado cómo puede comenzar a construir estructuras de datos agradables y modulares que sean claras y fáciles de usar, y que puedan comenzar a escalar bastante bien..
Bien, eso es lo más básico de las clases y los objetos, pero en este momento solo podemos usar clases como estructuras de datos, o contenedores de variables. Todo eso está bien, pero si queremos comenzar a realizar tareas más complejas con los datos que estamos manipulando, necesitamos una forma de introducir algo de lógica en estos objetos. La forma en que lo hacemos es con métodos..
Los métodos, esencialmente, son funciones contenidas dentro de una clase. Usted define uno exactamente de la misma manera que lo haría con una función, pero la diferencia es que la coloca dentro de una clase y pertenece a esa clase. Si alguna vez desea llamar a ese método, primero debe hacer referencia a un objeto de esa clase, al igual que las variables que estábamos viendo anteriormente..
Los métodos, esencialmente, son funciones contenidas dentro de una clase..
Voy a escribir un ejemplo rápido aquí en nuestra clase de mascotas para demostrar; vamos a crear un método, llamado 'suspensión', que imprimirá un mensaje cuando se llame por primera vez. Al igual que una función, voy a poner 'def' para 'definir', y luego voy a escribir el nombre del método que quiero crear. Luego vamos a poner nuestros paréntesis y punto y coma, y luego comenzar una nueva línea. Como de costumbre, cualquier cosa incluida en este método será sangrada un nivel adicional.
Ahora, hay otra diferencia entre un método y una función: un método siempre, siempre, siempre tiene que tener un argumento, llamado "yo" entre los paréntesis. Cuando Python llama a un método, lo que hace es pasar el objeto actual a ese método como primer argumento. En otras palabras, cuando llamamos doug.sleep ()
, Python realmente va a pasar el objeto 'doug' como un argumento al método de suspensión.
Veremos por qué eso es más tarde, pero por ahora debe saber que, con un método, siempre debe incluir un argumento llamado 'self' primero en la lista (si desea agregar más argumentos, puede agregarlos). después, exactamente como si estuvieras pasando varios argumentos a una función). Si no incluye ese argumento, cuando ejecute el código, se generará un error porque Python está pasando un argumento (este objeto 'self'), y el método dice: 'Hey, man, No tomo ningún argumento, ¿de qué estás hablando? '. Es lo mismo que si intentara pasar un argumento a una función que no acepta ningún argumento..
Así que aquí está lo que tenemos hasta ahora:
class pet: number_of_legs = 0 def sleep (self): doug = pet ()
Dentro de este método, vamos a escribir una declaración impresa así:
class pet: number_of_legs = 0 def sleep (self): imprimir "zzz" doug = pet ()
Ahora, si queremos usar este método, simplemente usamos una instancia de la clase de mascotas para referenciarlo. Al igual que el number_of_legs
variable, escribimos el nombre de la instancia (tenemos una llamada doug), luego un punto, luego el nombre del método incluyendo paréntesis. Tenga en cuenta que estamos llamando al modo inactivo sin argumentos, pero Python agregará ese argumento por sí mismo, por lo que vamos a terminar con la cantidad correcta de argumentos en total.
class pet: number_of_legs = 0 def sleep (self): imprime "zzz" doug = pet () doug.sleep ()
Si ejecuta este código, debería ver que imprime el mensaje que escribimos.
Genial, entonces, ¿qué tal si escribimos un nuevo método para imprimir cuántas patas tiene la mascota, para demostrar cómo puedes usar métodos para comenzar a manipular los datos dentro de la clase y para demostrar por qué debemos incluir este "yo" confuso? argumento. Hagamos un nuevo método, llamado 'count_legs
'.
Aquí es donde entra en juego el argumento del "yo". Recuerda cuando estábamos accediendo number_of_legs
¿Fuera de la clase y tuvimos que usar 'doug.number_of_legs' en lugar de 'number_of_legs'? El mismo principio se aplica; Si queremos saber qué contiene esa variable, debemos hacer referencia a ella especificando primero la instancia que contiene esa variable..
Sin embargo, no sabemos cómo se llamará la instancia cuando escribamos la clase, por lo que podemos evitar eso usando la variable 'self'. 'self' es solo una referencia al objeto que se está manipulando actualmente. Entonces, para acceder a una variable en la clase actual, simplemente necesita prefaciarla con 'self' y luego un punto, de esta manera:
class pet: number_of_legs = 0 def sleep (self): print "zzz" def count_legs (self): print "Tengo% s piernas"% self.number_of_legs doug = pet () doug.number_of_legs = 4 doug.count_legs ()
En la práctica, lo que esto significa es que dondequiera que escriba 'self' en su método, cuando ejecute el método ese self será reemplazado por el nombre del objeto, de modo que cuando llamemos 'doug.count_legs ()' the 'self' is reemplazado por 'doug'. Para demostrar cómo funciona esto con varias instancias, agreguemos una segunda instancia, que represente a otra mascota, llamada 'nemo':
class pet: number_of_legs = 0 def sleep (self): print "zzz" def count_legs (self): print "Tengo% s piernas"% self.number_of_legs doug = pet () doug.number_of_legs = 4 doug.count_legs () nemo = mascota () nemo.number_of_legs = 0 nemo.count_legs ()
Esto imprimirá un mensaje para 4 y luego 0 tramos, tal como queríamos, porque cuando llamamos 'nemo.count_legs (),' el 'self' es reemplazado por 'nemo' en lugar de 'doug'.
De esta manera, nuestro método se ejecutará exactamente como se esperaba, ya que la referencia 'self' cambiará dinámicamente según el contexto y nos permitirá manipular los datos solo dentro del objeto actual.
Lo principal que debe recordar acerca de los métodos es que son exactamente como las funciones, excepto que el primer argumento debe ser 'self' y que para hacer referencia a una variable interna debe comenzar con el nombre de la variable 'self'.
Solo como una nota: Puedes usar cualquier nombre en lugar de 'self' para tus métodos. -Los métodos aquí funcionarían igual de bien si cambiamos el nombre de la variable 'self' a cualquier palabra. Usar el nombre 'self' es simplemente una convención que es útil para los programadores de Python porque hace que el código sea mucho más estándar y fácil de entender, incluso si está escrito por otra persona. Mi consejo sería apegarse a las convenciones..
Ahora que hemos analizado lo básico, echemos un vistazo a algunas de las funciones más avanzadas de las clases y cómo pueden ayudar a que su programación sea más fácil de estructurar..
Lo próximo de lo que vamos a hablar es la herencia. Como su nombre podría sugerir, la herencia es el proceso de crear una nueva clase basada en una clase primaria y permitir que la nueva clase herede las características de la clase primaria. La nueva clase puede tomar todos los métodos y variables de la clase principal (a menudo llamada la clase 'base').
La herencia es el proceso de crear una nueva clase basada en una clase primaria.
Extendamos nuestro ejemplo de mascota para ver cómo esto podría ser útil. Si utilizamos "mascota" como nuestra clase principal, podríamos crear una clase secundaria que se hereda de la clase de mascota. La clase infantil podría ser algo como "perro" o "pez", algo que todavía es una "mascota", pero es más específico que eso. Un perro es una mascota, y hace las mismas cosas que hacen todas las mascotas, por ejemplo, come y duerme y tiene una edad y una cantidad de patas, pero hace otras cosas que son específicas de ser un perro, o al menos más específicas. que ser una mascota: los perros tienen pelaje, pero no todas las mascotas. Un perro puede ladrar o buscar un palo, pero no todas las mascotas.
Volviendo al punto, digamos que queríamos hacer una clase en nuestro programa para representar a un perro. Podríamos usar la herencia para heredar los métodos y las variables contenidas en "mascotas" para que nuestro perro pueda tener un "número de piernas" y la capacidad de "dormir", además de todas las cosas específicas para perros que podamos almacenar o hacer..
Ahora, es posible que se pregunte por qué no ponemos esos métodos y variables en la clase de perros y nos deshacemos de la clase de mascotas por completo. Bueno, la herencia nos brinda dos ventajas distintas sobre ese enfoque: una, si queremos un objeto que sea una mascota, pero que no sea un perro, una mascota genérica, si quiere, todavía podemos hacer eso. Dos, quizás más tarde queramos agregar un segundo tipo de mascota, tal vez un pez. Podemos hacer que la segunda clase también se herede de la mascota, por lo que ambas clases pueden compartir todo en la mascota, pero al mismo tiempo tienen sus propios métodos y variables más específicos que se aplican solo a ese tipo de objeto..
Nos estamos atascando un poco en la teoría aquí, así que vamos a escribir algo para que quede un poco más claro. Primero, vamos a escribir una nueva clase, llamada 'perro', pero esta vez, entre el nombre de la clase y los dos puntos, vamos a poner algunos paréntesis, y en ellos, vamos a escribir el nombre de la clase de la que queremos heredar, como si estuviéramos pasando un argumento a esta nueva clase, como si fuera una función.
A continuación, demos a esta clase un método simple para demostrar cómo funciona. Voy a añadir un 'ladrar
'Método que imprimirá' woof ':
class pet: number_of_legs = 0 def sleep (self): print "zzz" def count_legs (self): print "Tengo% s piernas"% self.number_of_legs class dog (pet): def bark (self): print "Woof"
Entonces, ahora veamos qué sucede si creamos una instancia de esta clase. Voy a llamar a nuestro nuevo perro 'doug' otra vez. Ahora, si llamamos doug.bark ()
:
class pet: number_of_legs = 0 def sleep (self): print "zzz" def count_legs (self): print "Tengo% s piernas"% self.number_of_legs class dog (pet): def bark (self): print "Woof" doug = perro () doug.bark ()
Como era de esperar, ladridos de doug. Eso es genial, pero aún no hemos visto nada nuevo, solo una clase con un método. Sin embargo, lo que la herencia ha hecho por nosotros es hacer que todas las funciones y variables de mascotas estén disponibles para nosotros a través de nuestro objeto 'doug', así que si hago algo como esto:
class pet: number_of_legs = 0 def sleep (self): print "zzz" def count_legs (self): print "Tengo% s piernas"% self.number_of_legs class dog (pet): def bark (self): print "Woof" doug = perro () doug.sleep ()
Entonces el método de suspensión también se ejecutará correctamente. En efecto, nuestro objeto doug pertenece tanto a la clase 'pet' Y a la clase 'dog'. Para asegurarnos de que las variables hagan lo mismo que los métodos, intentemos esto:
class pet: number_of_legs = 0 def sleep (self): print "zzz" def count_legs (self): print "Tengo% s piernas"% self.number_of_legs class dog (pet): def bark (self): print "Woof" doug = dog () doug.number_of_legs = 4 doug.count_legs ()
Puedes ver que doug actúa exactamente igual que antes, lo que demuestra que nuestras variables se están heredando. Nuestra nueva clase secundaria es simplemente una versión especializada de la principal, con alguna funcionalidad adicional pero conservando todas las funcionalidades anteriores.
Así que ahí lo tienen, una introducción rápida a la programación orientada a objetos. Manténgase atento a la próxima entrega de esta serie, donde trabajaremos con Python en la web.!