miércoles, 17 de abril de 2013

Clases y objetos python 3 parte (1/4)

Comenzamos con las clases y objetos :D,como bien decía a uno de los lectores del blog,aprendiendo a programar desde Unix(shell de Linux,FreeBSD,Mac,etc) podemos entender mas fácilmente o fácilmente la documentación de modulos de python,como gtk(pygtk),sys,os,re,PyQt4,etc,lo unico que pasa es que aun no están listos todos los tutoriales o por lo menos los fundamentales,en el cual algo de lo fundamental es saber trabajar y manejar objetos creados por clases, así que como es un tema un tanto largo dividiré este en cuatro partes,y esta es la primera.

Primero que nada necesitamos conocimiento basico para esto,asi que si no tienes ni idea de funciones,bucles y tipos de datos hecha un vistaso a los otros tutoriales:


Enlace

Primero que nada debemos saber que las clases son metodos de construcción para crear objetos,yo no explico mucho ya que voy directo a la practica pero hay que estar informado:

Python nos brinda la OOP:

La programación orientada a objetos o POO (OOP según sus siglas en inglés) es un paradigma de programación que usa los objetos en sus interacciones, para diseñar aplicaciones y programas informáticos. Está basado en varias técnicas, incluyendo herencia, cohesión, abstracción, polimorfismo, acoplamiento y encapsulamiento. Su uso se popularizó a principios de la década de los años 1990. En la actualidad, existe variedad de lenguajes de programación que soportan la orientación a objetos.

En la programación orientada a objetos, una clase es una construcción que se utiliza como un modelo (o plantilla) para crear objetos de ese tipo. El modelo describe el estado y el comportamiento que todos los objetos de la clase comparten. Un objeto de una determinada clase se denomina una instancia de la clase. La clase que contiene (y se utilizó para crear) esa instancia se puede considerar como del tipo de ese objeto. Por ejemplo, una instancia del objeto de la clase "Persona" sería del tipo "Persona".

Un ejemplo de instancia en un lenguaje de programación visual, sería tomar o arrastrar un objeto de la barra de herramientas o de la lista de librerías y colocarlo en el escritorio o escenario de trabajo (estamos creando una instancia de ese objeto, una copia). Si arrastramos 10 botones al entorno visual de trabajo, estamos creando una instancia del botón original, si a cada botón le cambiamos el nombre, tendremos 10 botones que heredan las mismas propiedades y métodos del objeto original. Tenemos como resultado que con un solo botón hicimos 10 y nuestro archivo pesara como si tuviese uno solo.

Una clase por lo general representa un sustantivo, como una persona, lugar o (posiblemente bastante abstracta) cosa - es el modelo de un concepto dentro de un programa de computadora. Fundamentalmente, encapsula el estado y el comportamiento del concepto que representa. Encapsula el estado a través de marcadores de datos llamados atributos (o variables miembro o variables de instancia), y encapsula el comportamiento a través de secciones de código reutilizables llamados métodos.

En la programación orientada a objetos, un método es una subrutina/función asociada exclusivamente a una clase (llamados métodos de clase o métodos estáticos) o a un objeto (llamados métodos de instancia).

Más técnicamente, una clase es un conjunto coherente que consiste en un tipo particular de metadatos. Una clase tiene una interfaz y una estructura. La interfaz describe cómo interactuar con la clase y sus instancias con métodos, mientras que la estructura describe cómo los datos se dividen en atributos dentro de una instancia.

Fuente Enlace

Bien,como dice arriba las clases heredan datos de otras clases,en esta entrada no vamos a hablar de herencia ni de todas sus capacidades,solo de como usar y definir una clase normal:

Las clases se definen con la palabra especial class,seguida del nombre de la clase y la herencia entre parentesis,en este caso no heredaremos nada,asi que podemos dejar los paréntesis en blanco o usar la palabra especial object:

Así se define una clase

class Miclase(object):

Y como en python,el algoritmo o el cuerpo del script/programa/exploit/etc debe ir identado:

class Miclase(object):
        # Algoritmo

Las funciones dentro de las clases se llaman métodos,y también tienen un rango de alcance similar al que habíamos comentado en las funciones def,local,global,etc.

En los metodos,siempre se les pasa por lo menos un argumento,self,este argumento lo que hace es que podamos usar todos los datos que se encuentran dentro de la clase desde metodos,para que estos no sean locales y invisibles ante otros métodos de la misma clase,asi definimos una función dentro de una clase(método):

def metodo(self):
Los métodos siguen teniendo todas las funciones de las funciones def,por ejemplo pasar mas argumentos o definiros desde el mismo:

def metodo(self,x,y, z = 1):

También las funciones return,print,etc(ver tutoriales de funciones)


Como bien dije,necesitamos saber el alcance de nuestros datos que están adentro de la clase,ya que existen datos locales para la clase,vistos para toda la clase:

class Miclase(object):
         var = 1 # Variable local vista por toda la clase,
                      # pero no por todo el programa 

También tenemos las variables locales de los metodos:


class Miclase(object):
         var = 1 # Variable local vista por toda la clase,
                      # pero no por todo el programa 
         def metodo(self):
               y = 2 # Variable local vista solo por este metodo
También las variable globales:

z = 0  # Variable global vista en todo el programa

class Miclase(object):
         var = 1 # Variable local vista por toda la clase,
                      # pero no por todo el programa 
         def metodo(self):
               y = 2 # Variable local vista solo por este metodo


Y por ultimo podemos pasar todas las variables,locales,locales de locales(metodos) o globales al uso de la función,con la palabra especial self

Por ejemplo un mal ejemplo:

#!/usr/bin/env python3

z = 0  # Variable global vista en todo el programa

class Miclase(object):
         var = 1 # Variable local vista por toda la clase,
                      # pero no por todo el programa 
         def metodo(self):
               y = 2 # Variable local vista solo por este metodo
         def llamada(self):
                print (y)

objeto = Miclase() # En un momento vemos que es esto
objeto.llamada() # Y esto

Ahora ejecutamos y como vemos da error en la linea 10 que es donde se llama a y:



Nota: si les da otro tipo de error es por la identacion(no hagan copy and paste) o arreglen la identacion.

Como vemos da un error de variable global,ya que python en el primer lugar que busca es en las variables globales, entonces esto se pudo haber resuelto definiendo y como global:

Asi:


#!/usr/bin/env python3


z = 0  # Variable global vista en todo el programa
y = 1 # Variable global
class Miclase(object):
         var = 1 # Variable local vista por toda la clase,
                      # pero no por todo el programa 
         def metodo(self):
               y = 2 # Variable local vista solo por este metodo
         def llamada(self):
                print (y)

objeto = Miclase() # En un momento vemos que es esto
objeto.llamada() # Y esto

O tambien python buscaria en las variables locales del metodo,asi que tambien podriamos solucionar ese error definiendo una variable local llama y:

Asi

#!/usr/bin/env python3

z = 0  # Variable global vista en todo el programa
class Miclase(object):
         var = 1 # Variable local vista por toda la clase,
                      # pero no por todo el programa 
         def metodo(self):
               y = 2 # Variable local vista solo por este metodo
         def llamada(self):
                y = 1 # Variable local

                print (y)

objeto = Miclase() # En un momento vemos que es esto
objeto.llamada() # Y esto

Y vean:


Pueden pensar que también podemos definir la variable como una local de clase:

#!/usr/bin/env python3

z = 0  # Variable global vista en todo el programa
class Miclase(object):
         var = 1 # Variable local vista por toda la clase,
                      # pero no por todo el programa 
         y = 1 # Local de clase
         def metodo(self):
               y = 2 # Variable local vista solo por este metodo
         def llamada(self):
                print (y)

objeto = Miclase() # En un momento vemos que es esto
objeto.llamada() # Y esto

Pero no :(

Porque python busca las variables en las funciones o en las variables,globales,para poder usar esa variable de clase local debemos usar la palabra especial self:


#!/usr/bin/env python3

z = 0  # Variable global vista en todo el programa
class Miclase(object):
         var = 1 # Variable local vista por toda la clase,
                      # pero no por todo el programa 
         y = 1 # Local de clase
         def metodo(self):
               y = 2 # Variable local vista solo por este método
         def llamada(self):
                print (self.y)

objeto = Miclase() # En un momento vemos que es esto
objeto.llamada() # Y esto

Y ahí esta la magia de self,bueno no y no es nada del otro mundo,poder usar esa variable con tan solo poner :

self.variable_de_clase
La magia esta en que podemos usar cualquier variable de la clase o metodo usando self,por ejemplo podemos definir una variable local de metodo y llamarlo,asi:

def metodo1(self);
      y = 1
      print (y)


Pero si en otro método queremos llamar esa variable,va a dar error de variable global:


#!/usr/bin/env python3

class Miclase(object):
    def metodo1(self):
        y = 1
        print (y)
    def metodo2(self):
        print (y) # Error :(

objeto = Miclase() # En un momento vemos que es esto 
objeto.metodo2() # Y esto


Como dije para eso usamos self,pero ahora desde la definición:

#!/usr/bin/env python3

class Miclase(object):
    def metodo1(self):
        self.y = 1 # Definimos una variable de rango self
        print (self.y)
    def metodo2(self):
        print (self.y) # Error aun

objeto = Miclase() # En un momento vemos que es esto 
objeto.metodo2() # Y esto

Las definicones de rango self,son variables locales de clase,por lo cual son visibles en toda la clase,siempre y cuando lleven self,en este caso sigue dando error,porque ?

Porque no hemos construido el objeto y aunque ya se definió la variable y en rango self,aun no la creamos si solo llamamos a metodo2:

Esto se puede arreglar de dos formas,llamando el metodo1 primero:

#!/usr/bin/env python3

class Miclase(object):
    def metodo1(self):
        self.y = 1 # Definimos una variable de rango self
        print (self.y)
    def metodo2(self):
        print (self.y) # Error aun

objeto = Miclase() # En un momento vemos que es esto 
objeto.metodo1() # Y esto
objeto.metodo2() # Y esto

Con esto python guarda en la memoria de la clase la variable de rango self y la podemos llamar desde otra:

Pero esto muchas veces es incomodo y algunas veces mala practica, así que lo que podemos hacer es construir(llamar),los dos metodos desde la misma clase con el metodo constructor __init__() el constructor __init__() ademas de que es el constructor del objeto,es el que le pasa los argumetos desde el script principal,ya que si creian que se pasaban los argumetos desde la clase:

class Miclase(argumeto1,argumeto2,etc):

Pues no,eso se usa para otra cosa que veremos mas adelante,desde __init__() se pasan los argumentos:

class Miclase(object):
         def __init__(self,argumento1,argumeto2):

Estos argumentos se los pasaremos a la hora de instanciar la clase,osea a la hora de crear el objeto:

objeto = Miclase()
 Y aquí justamente le pasamos los argumentos:

#!/usr/bin/env python3

class Miclase(object):
    def __init__(self,x,y):
        print ("%s %s!!!" %(x,y))

objeto = Miclase("Hola","Mundo")




Cabe mencionar que __init__() es el método principal de una clase,por la cual al instaciar no es necesario,llamarla así:

objeto = Miclase()

objeto.__init__()

Solo con usar


objeto = Miclase()

Usamos este método especial.

Asi que el ejemplo de arriba usando un constructor queda asi;

#!/usr/bin/env python3

class Miclase(object):
    def metodo1(self):
        self.y = 1 # Definimos una variable de rango self
        print (self.y)
    def metodo2(self):
        print (self.y) # Ya no hay Error
    def __init__(self): # Construimos la clase
        self.metodo1()
        self.metodo2()

objeto = Miclase() # Creamos el objeto


Aun así sigue teniendo el mismo problema,tiene que llamar los dos metodos para usar uno del otro :(

Si no queremos hacer esto,lo mejor es no usar clases y usar funciones.

En ocasiones,ya que podemos definir las variables como clase local o usar funciones anidadas,o mejor dicho metodos anidados:


#!/usr/bin/env python3

class Miclase(object):
    def metodo1(self):
        self.y = 1 # Definimos una variable de rango self
        return self.y # Devolvemos el valor para usarlo en el futuro
    def metodo2(self):
        print (self.metodo1()) # Llamos un metodo desde otro
       # Ya no hay Error

objeto = Miclase() # Creamos el objeto
objeto.metodo2() # Esta instancia llamara los dos métodos

O también con varibles de clase local como veíamos arriba o variables locales de tipo rango construcción


#!/usr/bin/env python3

class Miclase(object):
    def metodo2(self):
        print (self.metodo1) # Llamos un metodo desde otro
       # Ya no hay Error
   def __init__(self):
       self.y = 1 #Para esto son los constructores

objeto = Miclase() # Creamos el objeto y se llama al constructor
# Que crea la variable
objeto.metodo2() # Esta instancia llamara los dos métodos

pero no esto no demuestra el poder de las clases y de la OPP,ya que eso se puede hacer con funciones def, fácilmente,las clases son para crear objetos y así es como funcionan:

Supongamos que tenemos varias mascotas,las cuales requieren cuidados,limpiar sus gracias,darles de comer,etc lo que se nos ocurra,de ejemplo esas dos cosas,esas mascotas en python las podemos tratar como un objeto para administrarlas:

Ejemplo

Ese ejemplo es solo la idea pero podemos imaginar un poco:

Ejemplo

De momento es todo,luego podremos hacer algo mas interesante pero esa es la introducción.

3 comentarios:

  1. Que a las variables clase no se les dice variables de miembro?

    ResponderBorrar
    Respuestas
    1. Dani,si no vas a leer mejor no comentes |:(

      No mentira, pero si lo mencione, en el texto copy pegado de wikipedia, así que si no lees todo el articulo por lo menos has un :

      curl http://www.itimetux.com/2013/04/clases-y-objetos-python-3-parte-14.html | egrep --color "lo | que | pienses | que | no | dije"

      En este caso bastaba con

      curl http://www.itimetux.com/2013/04/clases-y-objetos-python-3-parte-14.html | egrep --color "variables * miembro"

      Ya si no regresaba nada comentabas :P

      Borrar

Los comentarios serán revisados antes de ser publicados.