Está en la página 1de 195

Introducción a Python

Juan Hernandez, 2011


vladjanicek@gmail.com
@vladjanicek
Python
● Lenguaje creado por Guido Van Rossum
● Es un lenguaje de alto nivel, intepretado/compilado
● Se enfoca en tener una sintaxis muy limpia
● Multiparadigma
● Es de tipado dinámico
● Fuertemente tipado
● Multiplataforma
● Incluye baterías ;)
Python
● Python fue creado en el Instituto Nacional de
Investigaciones Matemáticas y de Ciencias
Informáticas de Holanda para ser un sucesor
del lenguaje ABC
● Guido es el Benevolente Dictador Vitalicio
(BDFL)
● Python tiene varias implementaciones en
distintas plataformas de lenguajes
● Jython - JythonDroid
● IronPython
Caracteristicas y Paradigmas
● Al ser multiparadigma, no se obliga al
programador a adoptar un estilo particular
● Python trata todo como un objeto
● Python puede ser empleado en
● Programación estructurada
● Programación Orientada a Objetos
● Programación Funcional
● Programación Imperativa
Python y la filosofía SL
● Diseñado para su fácil extensión
● Al ser un proyecto libre, toma y entrega
caracteristicas de/para otros lenguajes y
plataformas
● Perl: regex
● Java: logging
● Lisp: lambda(), reduce(), map(), filter()
Zen de Python
● Hermoso es mejor que feo.
● Explícito es mejor que implícito.
● Simple es mejor que complejo.
● Complejo es mejor que complicado.
… etc etc etc …
● Lo podemos ver en el interprete al ejecutar
import this
Intérprete y el Modo Interactivo
● Python incluye un modo interactivo donde
podemos ejecutar cualquier sentencia
● Las instrucciones recibirán su resultado
de forma inmediata
● Esto resulta útil tanto para las personas
que se están familiarizando con el
lenguaje como también para los
programadores más avanzados
El Lenguaje y su sintaxis
● Los bloques de código están definidos por los dos
puntos “:”
def mifuncion(x):
print “hola curso”, x
● Utiliza espacios para definir el código perteneciente
a un bloque
● Espacios o Tabuladores. La consistencia es obligatoria
● Es una sintaxis limpia, clara y muy específica
● If x is not y: print “X no es Y”
Operadores Básicos
● + Suma y concatenación de cadenas de
caracteres
● - Resta y números negativos
● * Multiplicacion
● ** Exponente
● / Division
● % Modulus
Tipos de datos
● String/Unicode
● Lista
● Tupla (tuple)
● Diccionario
● Enteros (Int)
● Long
● Float
● Booleans
Baterías Incluidas??
● raw_input()
● len()
● max()
● in
● Ej: 'ton' in 'Python' evaluará False
Formatos de Strings
● %s = Strings
● %d = Números

ej: “Se llama %s y tiene %d hijos” %


('Pedro', 2)
Métodos de Strings
● split()
● join()
● find()
● strip()
● lower()/upper()
● replace()
● ljust()
● center()
Métodos de Strings
● rjust()
● swapcase()
● Isalpha()
● endswith()
Listas y Tuplas
● Listas son mutables, las tuplas no
● Para declarar listas, se usan corchetes
● Para declarar tuplas, se usan paréntesis
● Tanto las listas como las tuplas, pueden
tener elementos diversos
● Las listas se utilizan generalmente para
grupos de elementos variables en cantidad
● Las tuplas se utilizan para grupos de
elementos estáticos o de cantidad fija
Métodos de Listas
● append()
● insert()
● remove()
● pop()
● reverse()
● sort()
● sorted()
● extend()
Indices Python y Slicing
● Caracteristica muy poderosa de manejo de cadenas,
listas y tuplas
● Permite una precisión única, sólo obtenible en otros
lenguajes empleando mucho código
● Permite anidar sobre sentencias previamente
anidadas de forma ilimitada
● Se realiza con indices positivos y negativos entre
corchetes
● Para obtener un pedazo (slice) de mas de un
caracter, se utilizan los dos puntos “:”
Indices Python y Slicing
>>> x = 'Esta es mi cadena de caracteres'
>>> x[0]
'E'
>>> x[1]
's'
>>> x[­1]
's'
>>> x[­2]
'e'
>>> x[0:4]
'Esta'
>>> x[10:]
' cadena de caracteres'
Indices Python y Slicing
>>> x = ['abc', 'def']
>>> x[0]
'abc'
>>> x[­1]
'def'
>>> x[0][1]
'b'
>>> x[0][0:2]
'ab'
Diccionarios
● Conocidos tambien como matrices/arrays
asociativos
● Son componentes basados en llave:valor
● Son modificables y pueden tener cualquier
tipo de valor
● Son colecciones de datos llave/valor
● Son declarados con llaves “{}”
● Ej:
– xdict = {'mistring': 'python', 'miint': 12345}
Métodos de Diccionarios
● get()
● update()
● pop()
● clear()
● items()
● Ej: for k, v in x.items(): print "%s: %s" %(k, v)
for...in
● En Python podemos recorrer objetos
iterables con for
>>> a = [0, 1, 'hello', 'python']
>>> for i in a:
        print i 
0
1
hello
python
for...in
● Un atajo pitonico: xrange()
● xrange() nos permite generar un rango
sin generar una lista
>>> for i in xrange(0, 3):
        print i 
0
1
2
for...in
● Lo que en sintaxis C/C++/C#/Java sería...

for(int i=0; i<4; i=i+1) { print(i); }


for...in
● Para iterar sobre un diccionario
necesitamos la funcion items()

for k, v in x.items():
     print k, v
for...in
● Otro comando muy util y pitonico es
enumarate
>>> a = [0, 1, 'hello', 'python']
>>> for i, j in enumerate(a):
        print i, j
0 0
1 1
2 hello
3 python
range() and xrange()
● La función range() genera una lista temporal la cual es luego
manejada elemento por elemento
● La función xrange() produce un objeto iterable a través del cual
se puede pasar sin el peligro de lo que podría ser un objeto (lista)
muy grande
● for x in range(10000):
● Generará una lista de 10mil elementos y luego iterará sobre ella
● for x in xrange(10000):
● Generara un objeto iterable con 10mil enteros
type(range(10))
<type 'list'>

type(xrange(10))
<type 'xrange'>
for...in
● También podemos escapar de un for
utilizando brake
>>> for i in [1,2,3]:
       print i
break
1
while
● while funciona como lo hace en casi todos
los lenguajes de programación
● Lo hace al iterar de forma indefinida
evaluando una condición en cada ejecución
>>> i = 0
>>> while i < 10:
        i = i + 1
>>> print i
10
def...return
● Las funciones y los métodos en Python se
definen con la palabra def
● Para retornar un objeto, utilizamos la
palabra return

def f(a):
    return a    
def...return
● Los argumentos pueden tener valores
predeterminados

def f(a, b=2):
    return a + b
def...return
● También podemos retornar multiples
objetos

def f(a, b=2):
    return a + b, a – b
x, y = f(5)
def...return
● Las funciones también pueden tener un
numero indeterminado de argumentos
def a(*a, **b):
return a, b
if...elif...else
● Estructura de control basado en evaluaciones
condicionales
for i in range(3):
    if i == 0:
        print 'cero'
    elif i == 1:
        print 'uno'
    else:
        print 'es otro'
Introducción a la Programación
Orientada a Objetos
Programación Estructurada
● El paradigma al que tal vez estemos
acostumbrados
● Sus principales caracteristicas se basan en
estructuras de controles
● Condicionales, bucles, etc
● No hay relaciones entre la lógica y los datos
● Los datos son manejados a través de la lógica
– La única relacion es tener algo de datos, pasarlos a una
función y procesarlos esperando una respuesta
Objetos estructurados
● La meta es separar las tareas en:
● Estructuras de datos para la recepcion de datos,
sus diferentes estados y su almacenamiento
● Utilizar procedimientos para resolver problemas
● Sólo maneja estructuras de datos primitivas
● Si un comportamiento similar es deseado, la logica
es copiada y luego modificada
– Tampoco tiene relaciones entre si
Qué nos trae la Programación
OO?
● Es una mejora al paradigma estructural
● Puede acceder a estructuras y procedimientos
● Enfoque: Separa las tareas en objetos
● Se asemeja a los problemas reales
representandolos con código
● Integra la lógica y los datos
● Nuevos objetos pueden ser creados con
los ya existentes
● La herencia provee las relaciones
Objetos y Herencias

Transporte

Carro Moto Helicoptero

Toyota GM Honda HD
Cómo funciona?
● Clases: objetos contenedores o planos
● Instancias: objetos utilizados para crear objetos reales
● Funciones: son ahora parte de los contenedores y son
llamados métodos
● Si se desea crear nuevas relaciones sólo necesitamos
derivar nuevas subclases
● Los datos pueden ser “escondidos” con sus respectivas
interfaces para su acceso
● Crea su propio espacio de nombres (namespace) para
sus ahora relacionados atributos
namespaces

X Y

Nombre Nombre
Apellido Apellido
Direccion Direccion
Teléfono Ciudad
Cómo funciona?
● Encapsulamiento: la lógica y los datos están
integrados
● Los datos pueden actuar sobre si mismos (intercambio
de mensajes)
● Toda la funcionalidad esta dentro de si
● Derivación: objetos nuevos o similares pueden
ser creados
● Las modificaciones no afectan a los objetos existentes
● Polimorfismo: el código es menos específico de
un objeto
● Puede ejecutar el mismo código con diferentes objetos
Comparando paradigmas
Programación estructurada
f

x datos lógica datos f(x)

Programación OOP

datos datos datos


x x.f x.f()
lógica lógica lógica
Python y la Programación OO
● Python es un lenguaje orientado a objetos
● Python no requiere que utilices POO
● Utilizamos POO cuando estemos listos
● Guido se refiere a esto como a “Ver el bosque
a través de los arboles”
● Si no conoces la POO, lo podrás absorber
con muchas de las cosas de la
programación básica de Python
Clases
● Son:
● Contenedores pero mas en definición q en si un objeto
● Planos que cobran vida una vez se crea una instancia
● Proveen un espacio de nombres para sus elementos
● Al utilizar sus elementos, le dará la relación entre si
● Pueden:
● Ser derivadas en subclases
● Emular o derivar tipos de datos Python
Atributos de las clases
● Las clases tienen atributos
● Objetos miembros, elementos, etc
● Atributos (datos) de clases
● También conocidos como miembros
estáticos/privados
● Métodos
● No existen sin una instancia
● La unión (binding) es requerida para su
ejecución
A qué se parece una clase?

Atributos de las clases

Métodos sin unión (unbound)

● Atributos de datos (miembros estaticos de la clase)


● Compartidos entre todas las instancias
● Métodos
● Requieren la unión (binding) para ser ejecutadas
Qué podemos hacer con las
clases?
● Hay dos cosas que podemos hacer con
las clases
● Hacer un objeto de ellas (instanciar)
● Crear una subclase
Creando las clases
● Se utiliza la palabra reservada class y
luego definimos atributos
● Las clases pueden tener también cadenas
de caracteres para documentación
● La referencia de la instancia, llamada self
es obligatoria
Creando las clases
class LibretaTelefonica(Object):
    “Mi primera clase”
    version = 1.0
    def __init__(self, nm, nt):
        self.nombre = nm
        self.telefono = nt
    def actualizarTel(self, nuevo):
        self.telefono = nuevo
Instancias
● Las clases cobran vida!
● Se crean objetos desde los planos (clase)
● La creación de objetos es también referida como
“instanciación”
● Si se tiene un inicializador (__init__) es ejecutado despues
de la instanciación pero antes de que tengamos el objeto
● Las instancias comparten los atributos estáticos
● Los miembros estáticos son compartidos por todas las
instancias
● __del__ es el equivalente al destructor pero no se
recomienda su uso
Extendiendo Python
Extendiendo python: for
● En Python generalmente definimos las
iteraciones for como un bloque de condigo
● A diferencia de los demás lenguajes, Python
no necesita la creación de un contador para
poder navegar sobre un objeto iterable
● Python nos ofrece una manera aún mas
sencilla, pitónica y efectiva para la creacion
dinámica de secuencias: for dentro de listas
o list comprehensions
list comprehensions
● Creando un for dentro de una lista
[x for x in xrange(1, 7374, 233)]
● Si revisamos que tipo de objeto es,
podremos observar que es una lista
● Puede recibir condicionales y de evaluar
verdadero, retornaran el objeto del
momento del ciclo
list comprehensions
● Evaluemos si un número en una sequencia
es par
>>> [x for x in xrange(1, 20) if x % 2 is 0]
… [2, 4, 6, 8, 10, 12, 14, 16, 18]
● Evaluemos si es impar
>>> [x for x in xrange(1, 20) if x % 2 is not
0]
… [1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
Extendiendo python: for
● Podemos inclusive dar un poco mas de
complejidad usando funciones
def f(x):
if x % 2 is 0:
y = True
else:
y = False
return y
Extendiendo python: for
● Una vez tengamos la funcion f() definida,
podremos utilizarla como evaluación

>>> [x for x in xrange(1, 20) if f(x)]


… [2, 4, 6, 8, 10, 12, 14, 16, 18]
Extendiendo python: for
● Podemos tener varias condiciones en la
ejecucion del for
● Supongamos que ahora queremos
obtener los numeros impares y además
necesitamos saber cuales de esos
números, tienen raices cuadradas exactas
● import math
– Módulo de métodos matemáticos en Python
Extendiendo python: for
● Definimos la funcion que evalua las raices cuadradas y
nos dice si estas son exactas o no com math.sqrt(x) y el
método float is_integer()

def exacta(x):
y = math.sqrt(x)
if y.is_integer():
z = True
else:
z = False
return z
Extendiendo python: for

[x for x in xrange(1, 100) if not f(x) and exacta(x)]


[1, 9, 25, 49, 81]
Extendiendo python: for
● Como vemos, podemos definir en una sóla
línea, parámetros condicionales que en
otros lenguajes nos tomaría en muchos
casos, hasta decenas de líneas
● El propósito real es retornar una lista con
los valores evaluados
● Podemos tener N número de condicionales
y al basarnos en que en python, todo es un
objeto, evaluar con practicamente
cualquier objeto
Funciones anónimas: lambda()
● Python maneja la creación de funciones
anónimas en el momento de ejecución
● Son funciones que no estan unidas
(unbounded) a un nombre
● Se crean empleando la palabra lambda()
● Es también utilizado en conjunto con
filter(), map() y reduce()
Funciones anónimas: lambda()
● Una función ● Una función
regular anónima

def f (x): g = lambda x: x**2


return x**2 print g(8)
print f(8)
Funciones anónimas: lambda()
● Como podemos ver, f() y g() hacen
exactamente la misma operación pero de
distintas maneras
● Notemos como la expresion lambda no tiene
una sentencia de salida o return ya que
contiene una expresión que siempre es
devuelta
● También notemos como podemos colocar una
expresión lambda en practicamente cualquier
sitio sin siquiera tener que asignarla a una
variable
Funciones anidadas
● Python nos ofrece el uso de funciones anidadas o
funciones dentro de funciones. A partir de Python
2.2 podemos ejecutarlas progresivamente o de
forma directa

def incrementor(n):
def suma(x):
return n + x
return suma
Funciones anidadas
● Y las dos maneras de ejecutar son,
indirecta
yy = incrementor(10)
yy(20)
... 30
● O directa...
incrementor(22)(33)
...(55)
Funciones anónimas: lambda()
def incrementor (n):
return lambda x: x + n

f = incrementor(2)
g = incrementor(6)
print f(42), g(42)

print make_incrementor(22)(33)
Funciones anónimas: lambda()
● Como vimos, definimos la función
incrementor que crea de forma inmediata
una funcion que realiza la suma y la
retorna
● Ahora podemos crear múltiples funciones
incrementadoras y asignarles variables y
usarlas una independiente de la otra
● Como la ultima función demostró, estas no
tienen que ser previamente definidas y
podremos usarlas y luego olvidarlas
lambda()
● Ahora demos un paso mas adelante: map(),
reduce() y filter()
● Todos estas funciones esperan dos
argumentos: una función y una lista
● Para probar estas funciones, crearemos una
lista de valores enteros

foo = [2, 18, 9, 22, 17, 24, 8, 12, 27]


lambda()
● filter() llama cada elemento de la lista en
nuestra función lambda y retorna una
nueva lista con los elementos que
coincidieron, o fueron True

print filter(lambda x: x % 3 == 0, foo)


[18, 9, 24, 12, 27]
lambda()
● map() se utiliza para convertir nuestra
lista. La funcion se ejecuta sobre todos
los elementos de la lista provista

print map(lambda x: x * 2 + 10, foo)


[14, 46, 28, 54, 44, 58, 26, 34, 64]
lambda()
● reduce() es algo especial en comparacion
con map() y reduce()
● La función debe recibir dos argumentos
● La función es llamada con los dos primeros
elementos y luego ese resultado es llamado
con el tercer elemento

print reduce(lambda x, y: x + y, foo)


139
Ejercicios Lambda
● Crear una función lambda anidada a una
función regular que reciba el string “esta
ahora lloviendo perros y gatos” y nos
retorne cuantos caracteres tiene cada
palabra
● Luego, una vez la terminemos, hacerla en
una sola línea únicamente con una
función lambda, luego convertir esa lista
retornada a string y mostrarlo en el index
de web2py
Extendiendo Python
Módulos: tweepy
tweepy
● Una vez instalamos el módulo tweepy, podremos acceder
a la mayor parte de las funcionalidades de twitter
● Import tweepy
● Fácilmente podremos ver los tweets públicos que
contengan la palabra “Python” con el método search()

search_tweets = tweepy.api.search('python')
for tweet in search_tweets:
print tweet.text
tweepy
● El tipo de objetos que nos retorna el
método search() nos provee de muchos
objetos de los cuales obtener información
type(public_tweets[0])
<class 'tweepy.models.SearchResult'>
● Entre estos, tenemos la información de
cada usuario que escribio el tweet
[x.from_user + ": " + x.text for x in
search_tweets]
tweepy
● Así también podemos utilizar public_timeline() para
ver los tweets públicos en general
public_tweets = tweepy.api.public_timeline()
[x.text for x in public_tweets]
● Notemos como aqui los objetos son algo diferentes
y tienen otras propiedades
[x.user.name + ": " + x.text for x in public_tweets]
● Sucede esto porque twitter limita los objetos via REST y
mas aún, cuando hay una búsqueda a diferencia del
Timeline público
● Si deseamos ver el TL de un usuario en específico,
utilizamos el método user_timeline()
tweepy
● Métodos disponibles
● x.user: retorna un objeto user que contiene
las propiedades del usuario como nombre,
nick, url, etc
● x.created_at: retorna un objeto date con el
momento de la creación de ese tweet
● x.source: retorna la informacion de donde fue
escrito ese tweet, si fue via web o algún
cliente o API especial
tweepy
● User:
● u = tweepy.api.get_user('usuario')
● u.follow: nos permite seguir al usuario
● u.followers: nos retorna objetos user de sus
seguidores
● u.following: nos retorna objetos user de las personas
a las que ese usuario sigue
● u.id: el id en twitter del usuario
● u.lists: las listas del usuario
● u.profile_image_url: la url que contiene la imagen del
perfil del usuario
tweepy
● User:
● u.name: el nombre del usuario
● u.screen_name: el nick del usuario
● u.url: la url definida por el usuario
● u.status: muestra el último estatus en twitter
● u.statuses_count: muestra cuantos estatus
han sido escritos por ese usuario
Autenticación tweepy
● Recientemente twitter cambio el sistema de
autenticación
● Por varios años, twitter utilizó un sencillo
esquema usuario/password
● Para conveniencia de los usuarios, comenzó a
implantar la autenticación OAuth
● OAuth es un estándar abierto para autorizaciones.
Permite que los usuarios compartan recursos
privados en un sitio sin tener que entregar su
login/password
Manejo de Archivos
Manejando archivos
● Los módulos de archivos pueden ser utilizados
para acceder no solo archivos normales de disco,
sino también, cualquier otro tipo de archivo que
maneje esa abstracción
● Podremos conseguir muchos casos en los cuales
estaremos tratando con objetos parecidos a un
archivo al ir avanzando
● Alguno de estos ejemplos incluirian abrir un URL para
leer una pagina en tiempo real y ejecutando un
comando en un proceso separado
Manejando archivos
● La función incluída open() regresa un objeto
archivo que luego es utilizado para todas las
operaciones del archivo en cuestión
● Hay un gran número de funciones que
retornan un archivo o un objeto de
propiedades parecidas a un archivo.
● Una de las principales razones de esta
abstracción es que muchas de las estructuras de
entrada y salida (input/output) prefieren tener
este tipo de abstracción
Manejando archivos
● Mantienen este comportamiento ya que
provee consistencia en su comportamiento
así como en su implementación
● Sistemas operativos como Unix y Linux
utilizan estructuras de caracteristicas de
archivos para su interfaz arquitectónica y
subyacente para su comunicación
● Recordemos: los archivos son sólo una sequencia
continua de bytes. Donde sea necesario que
datos sean enviados, generalmente envuelve
una cadena de bytes
Manejando archivos
● La función open() (y file()) nos provee la
interfaz general para iniciar el proceso de
entrada y salida input/output.
● La interfaz open() retorna un objeto luego
de una apertura exitosa del archivo
● Sino arrojará una excepción
● Al fallar, Python generará un IOError
Manejando archivos

file_object = open(file_name, access_mode='r', buffering=-1)


● Aquí, file_name es un string que contiene el
nombre del archivo a abrir
● Este puede ser una ruta relativa o absoluta
● El access_mode o modo de acceso, es una
variable opcional que define que tipo de acceso
tendremos sobre el archivo a abrir
● Todos los archivos abiertos con “w” serán
truncados al inicio una vez se confirmen que
existen y luego, el archivo será recreado
Manejando archivos
● Cualquier archivo abierto con “a” sera
colocado en memoria para anexarle
contenido a su final (append)
● Todos estos archivos estarán en memoria
después del EOF, inclusive si sobre el objeto
se realiza alguna búsqueda
● Si el archivo no existe, este será creado
Manejando archivos
fp = open('/etc/motd') #Lectura
fp = open('test', 'w') #Escritura
fp = open('data', 'r+')
#Lectura/Escritura
fp = open(r'c:\io.sys', 'rb') #Binario para lectura
Manejando archivos
● El método read() se utiliza para leer bytes directamente
hacia un string con la cantidad de bytes específica
● Si esta cantidad no existe, el archivo será leído hasta el final.
● Esta caracteristica está a punto de ser removida de Python
● El método readlines() lee una línea del archivo en
memoria
● Lee todos los bytes hasta que consigue un caracter de corte o
de línea nueva
● La línea, incluyendo sus caracteres de fin, son
retornados como un string
● Como read(), este provee la opción de límite de bytes
Manejando archivos
f = open('/etc/hosts')

for x in f.readlines():
print x,

127.0.0.1 localhost
127.0.1.1 juan
127.0.1.1 af.local
192.168.1.100 eqn.local

f.close()
Manejando archivos
● Unas de tantas formas pitónicas de abrir
archivos
for line in open('/etc/hosts', 'r'):
print line,
● O con list comprehensions hacia una lista,
separando en cada linea, un objeto
[line for line in open('/etc/hosts', 'r')]
Manejando archivos
f = open('miarchivo.xxx, 'r')
data = [line.strip() for line in f.readlines()]
f.close()
Manejando archivos
● El método write() toma un string que
consiste en una o más líneas de texto y lo
escribe en un archivo
● El método writelines() opera en una lista
justo como readlines() pero toma los
strings y los escribe a un archivo.
● Los caracteres de fin de línea no son
insertados en cada línea y de ser deseado,
deben ser agregados al fin de cada una
Manejando archivos
f = open('miarchivo4.txt', 'w')
for x in range(100):
f.write('xxx' + '\n')
Python avanzado:
Profundizando Paradigmas:
Decoradores
Atributos de clase
● Las clases tienen atributos
● Objetos miembro, elementos, etc
● Atributos (Datos) de clase
● Miembros estáticos/privados
● Métodos
● Unbound o q no pertenecen a instancia
alguna
● Requieren la unión (Binding) para su
ejecución
Métodos estáticos
● No necesitan la unión (Binding) o creación de una
instancia para ser ejecutados
● Los métodos estáticos pueden ser ejecutados en cualquier
momento y cualquier sitio de nuestro programa siempre
que su clase pertenezca a la ruta o este correctamente
importada
● Podemos crearlos con el metodo staticmethod() o con el
decorador @staticmethod
● Los ejecutamos mediante la instancia o directamente
● C.f()
Métodos estáticos

class MiClase:
def metodoestatico():
print “Este es mi metodo estatico”
metodoestatico =
staticmethod(metodoestatico)
Métodos estáticos
● Utilizando decoradores de función

class MiClase:
@staticmethod
def metodoestatico():
print “Este es mi metodo estatico”
Métodos estáticos
● Podemos ejecutar el método tanto en
instancia como independiente del binding
● Este tipo de métodos puede ejecutarse de
forma mas rápida y limpia empleando los
decoradores
Decoradores
● Un decorador en Python realiza una tarea
parecida a lo que C nos provee en una
macro de preprocesamiento
● En C# y Java existen enfoques parecidos
y estos son definidos como annotations,
permitiendonos hacer tareas adicionales
en los elementos
● Los decoradores nos permiten injectar o
modificar código en funciones o clases
Decoradores
● La aplicación de un decorador es
empleada con la utilización del
ampersand (@) antes de la palabra
utilizada
● Es una excelente forma de definir puntos
de entrada y salida de una función
● Como definir directivas de seguridad, rastreo,
bloqueo
Decoradores
● Con decoradores, el código se vería así:
@entryExit
def func1():
print "dentro de la func1()"
@entryExit
def func2():
print "dentro de la func2()"
Decoradores
● Un decorador es aplicado a la definición
de la función al colocarlo en la línea
anterior a su definición
● Cuando el compilador pasa sobre este
código, la función es compilada y el
objeto resultante es pasado al código del
decorador, lo que hará algo para producir
un objeto que sera sustituido por la
función inicial
Decoradores
● El decorador puede practicamente hacer cualquier cosa que Python nos permita
● Esperamos que el código de la función sea ejecutado pero no es un requerimiento
#decorador.py
class MyDecorator(object):
def __init__(self, f):
print "dentro de MyDecorator.__init__()"
f() # Muestra q la definición de la función ha sido completada
def __call__(self):
print "dentro myDecorator.__call__()"
#decorador2.py
@MyDecorator
def aFunction():
print "dentro de aFunction()"
print "Termino decorando aFunction()"
aFunction()
Decoradores
● Al ejecutar este código veremos como se
imprime lo siguiente

dentro de MyDecorator.__init__()
dentro de aFunction()
Finished decorating aFunction()
dentro myDecorator.__call__()
Decoradores
● Notemos como el constructor de MyDecorator es
ejecutado en el punto de decoración de la función.
● Notemos como constructor del decorador recibe el
objeto de la función a decorar
● Típicamente, se captura el objeto de la funcion en el
constructor y luego se usa en el método __call__
● Si aFunction() es llamada despues de que ha sido
decorada, obtendremos un comportamiento
totalmente diferente
● __call__() será llamado en vez del código original
Decoradores
● Esto es debido a que el acto de
decoración reemplaza el objeto original
de la funcion con el resultado del
decorador
● En nuestro caso, el objeto del método
MyDecorator reemplaza aFunction.
Decoradores
#decorator3.py
class entryExit(object):
def __init__(self, f):
self.f = f
def __call__(self):
print "Entrando", self.f.__name__
self.f()
print "Saliendo", self.f.__name__
#decorator4.py
@entryExit
def func1():
print "inside func1()"
@entryExit
def func2():
print "inside func2()"
Decoradores
● Ejecutamos las funciones
func1()
func2()
● Podemos ver que las funciones decoradas tienen
“entrando” y “saliendo” haciendo seguimientos a la
llamada
● El constructor guarda el argumento que es el objeto
de la función.
● En la llamada, usamos el atributo __name__ para
mostrar cual es el nombre de la función para luego
llamarla por si mismo
Usando funciones como
decoradores
● La unica restricción en el resultado de un decorador
es que esta debe ser posible llamarla para que
pueda reemplazar la función decorada
● En los ejemplos anteriores hemos reemplazado la
función original con un objeto de una de una clase
que tiene un método __call__()
● También, podemos llamar objetos desde una
funcion, asi que podremos reescribir el ejemplo
anterior usando una función en vez de una clase
Decoradores
#decorator5.py
def entryExit(f):
def new_f():
print "Entrando", f.__name__
f()
print "Saliendo", f.__name__
return new_f
#decorator6.py
@entryExit
def func1():
print "dentro func1()"
@entryExit
def func2():
print "dentro func2()"
Decoradores
● Lo ejecutamos de la misma manera
func1()
func2()
print func1.__name__ # veamos su salida
● new_f() es definido dentro del bloque de codigo de
entryExit() y es creado y retornado con esa función
● Notemos como es capturado f() y luego desplegado
● Una vez new_f() ha sido definido dentro del bloque de
código, es retornado por entryExit()
Decoradores
● La salida de print func1.__name__ es new_f ya que
new_f ha sido sustituida por la decoración
● Si este es un problema, podemos cambiar el nombre
de la función antes de que esta sea retornadadef
entryExit(f):
def new_f(f):
print "Entrando", f.__name__
f()
print "Saliendo", f.__name__
new_f.__name__ = f.__name__
return new_f
Python Avanzado:
Shell Scripting y
Programación Estructurada y Funcional
Programación de shell scripts
● Un shell script es un miniprograma que
generalmente automatiza tareas especificas en la
administración de sistemas
● Shell es el nombre utilizado por la interfaz de comandos
– Bash, ksh, csh, etc
● Se comenzó a utilizar en entornos UNIX en los años
setenta
● Generalmente empleado en los viejos tiempos con
las mismas interfaces de comandos
Programación de shell scripts
● También, unido al poderoso motor
UNIX/Linux de ejecución y programación de
tareas, puede realizarse cualquier tarea
● Desde el mas mínimo programa que copie un
archivo de un sitio a otro, al más complejo
intercambio y modificación de datos entre
multiples bases de datos
● Generalmente el interprete está localizado
en /usr/local/bin/python o /usr/bin/python
Programación de shell scripts
● En sistemas Windows, generalmente está
instalado en un directorio parecido a
C:\Python27
● Depende de la versión
● Si queremos agregar Python a nuestra
ruta, podemos agregar esto al PATH de
Windows
● set path=%path%;C:\python27
Programación de shell scripts
● En shell scripting, es necesario definir en la primera
línea, el ambiente en que se ejecutará el script
● Generalmente definido por #!/RUTA_DEL_AMBIENTE
● En Python, al contar con varias ramas y/o versiones,
podremos tener varios ambientes en nuestro
sistema
● Ambientes independientes y el manejo de distintas
versiones lo veremos más adelante
● Definido la mayoría de las veces como
#!/usr/bin/python
Programación de shell scripts
● Creemos nuestro primer script llamado script001.py
● Agreguemos el ambiente
# type python
python is /usr/bin/python
● Ingresemos el código de nuestra aplicación
● Verifiquemos que tenga permisos de ejecución
● Ingresemos los parámetros necesarios para su ejecución
● Ejecutémoslo directamente sin invocar el interprete
./script001.py
shell script: asignatura
● Crear un script que realice estas tareas
● Espere entre uno y tres argumentos
-d, -h, -v
● Imprima un error si no consigue al menos un argumento
● Muestre un texto de ayuda si su argumento es --help
● Cada argumento debe concatenarse uno con otro y retornar una
cadena de texto
-d: Mostrará la fecha de hoy
-h: Mostrará la hora
-v: Mostrará la versión
● Si se encuentra que hay mas de un argumento, separarlo por comas
● --help sólo puede existir como el primer argumento. Si hay comandos
después de él, ignorarlos.
– De no estar en el inicio, imprimir error
Programación funcional
● Comencemos por la pregunta más dificil:
Qué es programación funcional??
● Las funciones son objetos de primera clase, lo
que significa que todo lo que pueda hacerse
con datos, será realizado por las funciones
● La recursividad es utilizada como una
estructura de control primaria
● Se enfoca en el procesamiento de listas (Lisp:
LISt Processing). Las listas son frecuentemente
utilizadas con recursividad en sublistas como
un reemplazo de los bucles
Programación funcional
● La PF se preocupa en que será procesado
en vez de como lo procesará
● La PF evita y hasta prohibe sentencias y
en vez de utilizarlas, trabaja con la
evaluación de expresiones
● En otras palabras, funciones + argumentos
Python y la programación
funcional
● Python ha tenido la mayoría de las caracteristicas
de la PF desde la versión 1.0
● Pero como la mayor parte de las caracterisiticas de
Python (Y tal vez su mayor ventaja sobre otros
lenguajes) es que están presentes en una mezcla de
paradigmas
● Como las caracteristicas de Programación
Orientada a Objetos (POO, OOP), podemos usar lo
que queremos e ignorar el resto
● Hasta que lo necesitemos
Python y la programación
funcional
● En la versión 2.0, Python trajo una característica muy
amigable con introducir list comprehensions
● Mientras que list comprehensions no agregan ninguna
caracteristica nueva, hace que muchas de las viejas
características sean muchísimo mas amigables
● Los elementos básicos de la PF son las funciones map,
reduce y filter y el operador lambda
● Dificil de entender al principio, estas pocas funciones (y los
operadores básicos) son casi suficientes para escribir
cualquier programa
Python y la programación
funcional
● Las sentencias de control de flujo de datos
(flow control statements) pueden ser
manejadas en su totalidad en un estilo
funcional usando exclusivamente las
funciones y operadores de la PF
● Mientras que eliminar los comandos de
control de flujo de datos puede ser solo
necesario para algo muy específico, el
conocer este enfoque nos ayuda de forma
dramática a escribir un código más eficiente
PF
● Lo primero que debemos pensar en
nuestro ejercicio de eliminación es el
hecho de los “atajos” a la hora de evaluar
tipos de datos booleanos
● El código siguiente nos provee una
versión de los bloques if/else/elif
asumiendo que cada bloque llama una
función.
PF
# Control básico basado en sentencias
if <cond1>: func1()
elif <cond2>: func2()
else: func3()
# Equivalente
(<cond1> and func1()) or (<cond2> and func2()) or
(func3())
PF
# Ejemplo
>>> x = 3
>>> def pr(s): return s
>>> (x==1 and pr('uno')) or (x==2 and pr('dos')) or (pr('otro'))
'otro'
>>> x = 2
>>> (x==1 and pr('uno')) or (x==2 and pr('dos')) or (pr('otro'))
'two'
Python Avanzado:
Expresiones Regulares
Introducción
● Las expresiones regulares son la forma
más poderosa de buscar, reemplazar y
coincidir código acorde ciertos
parámetros que emplearemos
● Si hemos usado expresiones regulares en
otros lenguajes (específicamente PERL y
PHP) la sintaxis nos parecerá muy
parecida y con solo leer la documentación
podremos fácilmente utilizar el módulo
Introducción
● Los strings en Python ya tienen métodos de búsqueda
(index, find, and count), de reemplazo (replace) y de
análisis (split) pero estos son limitados para los casos
generalmente simples
● Estos métodos generalmente buscan bloques de código
y normalmente son sensibles a las mayúsculas
● Para poder emular búsquedas insensibles en un string,
debemos normalmente usar lower() o upper()
● replace() y split() tienen los mismos inconvenientes
Introducción
● Si lo que necesitamos podemos usar métodos de
Strings, debemos usarlas.
● Son rápidas y faćiles de desarrollar y entender
● Si nos vemos en situaciones donde estamos usando
muchos métodos de Strings anidados con
condicionales junto a split() y join(), puede que
necesitemos usar expresiones regulares
● Aunque la sintaxis de las expresiones regulares es
cerrada y distinta al código normal, el resultado
puede resultar mas legible que el código regular
Expresiones regulares
● Comencemos a estudiar el uso de las
expresiones regulares con algunos de los
casos mas típicos que enfrentamos a la
hora de un desarrollo
● Crearemos a través de distintos ejemplos,
la estandarización de las direcciones
introducidas por los usuarios
Expresiones regulares
>>> s = '100 NORTH MAIN ROAD'
>>> s.replace('ROAD', 'RD.')
'100 NORTH MAIN RD.'
>>> s = '100 NORTH BROAD ROAD'
>>> s.replace('ROAD', 'RD.')
'100 NORTH BRD. RD.'
>>> s[:-4] + s[-4:].replace('ROAD', 'RD.')
'100 NORTH BROAD RD.'
>>> import re
>>> re.sub('ROAD$', 'RD.', s)
'100 NORTH BROAD RD.'
Expresiones regulares
● Nuestra meta es estandarizar una
direccion donde “ROAD” sea siempre
reemplazado por “RD”
● A primeras podemos ver como con un
simple método replace()
● Como el texto ya estaba en mayúscula, no
había problema con la sensibilidad de las
mayúsculas
● Una vez conseguimos “ROAD”, este es
reemplazado sin problemas
Expresiones regulares
● Desafortunadamente, este no es el unico
lugar donde conseguimos esta palabra
● El primer problema lo encontramos
cuando “ROAD” se encuentra dos veces
en el texto
● También está en “BROAD”
● Podemos resolverlo tambien indexando
un poco los strings pero el patrón
dependerá de cuan largo sea el String
Expresiones regulares
● Si quisieramos reemplazar 'STREET' con 'ST.',
necesitariamos usar algo como s[:-6] y
s[-6:].replace(...)
● Es hora de usar expresiones regulares
● En Python, las utilizamos con el módulo re
● Veamos el primer parámetro, “ROAD$”
● Esta es una simple expresión regular que tendrá
una coincidencia en el final del String
– $ aplica para el final del String
– ^ aplica para el inicio del String
Expresiones regulares
● Usando el método re.sub(), búscamos el string “s”
por la expresión regular “ROAD$” y la
reemplazamos por “RD”
● Esta coincide con “ROAD” al final del String y no
reemplaza “BROAD” ya que se encuentra en el
medio
● Este enfoque es más efectivo pero que sucedería si
la dirección es “100 BROAD”?
● Es necesario que podamos coincidir palabras
completas para poder tener éxito en nuestra
búsqueda
Expresiones regulares
>>> s = '100 BROAD'
>>> re.sub('ROAD$', 'RD.', s)
'100 BRD.'
>>> re.sub('\\bROAD$', 'RD.', s)
'100 BROAD'
>>> re.sub(r'\bROAD$', 'RD.', s)
'100 BROAD'
>>> s = '100 BROAD ROAD APT. 3'
>>> re.sub(r'\bROAD$', 'RD.', s)
'100 BROAD ROAD APT. 3'
>>> re.sub(r'\bROAD\b', 'RD.', s)
'100 BROAD RD. APT 3'
Expresiones regulares
● Lo que queríamos al inicio era coincidir “ROAD” cuando
estuviese al final del String y que fuese una palabra
entera, no parte de otra
● Para expresar esto en expresiones regulares, debemos
utilizar “\b” que significa literalmente “una división de
palabras debe existir”
● En Python a veces puede hacerse complicado por el
hecho de que el caracter “\” debe tener su escape
● A veces se refiere a esto como “la plaga del backslash”
Expresiones regulares
● Para poder evitar este problema, podemos utilizar
strings “crudos” al iniciarlos con el caracter “r”
● Ej: r”\bxxx”
● Esto le dirá a Python que nada debe ser escapado
● '\t' es el caracter de tabulación, pero r'\t' pasa a ser el
caracter backslash “\” seguido por la letra “t”
● Es recomendable siempre utilizar Strings crudos
ya que de otra forma será bastante confuso
Expresiones regulares
● Luego vimos que tenemos otros errores en
casos distintos
● Al ver que la direccion tenía “ROAD” pero
este no se encontraba al final del String ya
que esta tenía el número de apartamento
● Para resolver esto, quitamos el caracter
“$” y lo reemplazamos por “\b” ya que
tanto el inicio de línea como el corte por
otra línea, tendrán coincidencia
Expresiones regulares
● Ahora crearemos expresiones regulares que nos
permitirá identificar números romanos
● Usaremos siente números y los repetiremos
conforme sea necesario para formar cantidades
● I=1
● V=5
● X = 10
● L = 50
● C = 100
● D = 500
● M = 1000
Expresiones regulares
● Estas son las reglas que debemos considerar:
● Los caracteres se suman conforme la repetición hasta tres veces. I
es 1, II es 2 y III is 3. VI es 6 (literalmente, “5 mas 1”), VII es 7 y VIII
es 8.
● Los caracteres (I, X, C, y M) pueden ser repetidos hasta tres veces.
Al llegar 4, necesitamos sustraer uno del caracter siguiente de
mayor valor.
● No podemos representar 4 como IIII; en vez de eso, es representado
como IV (“1 uno menos de 5”). El número 40 es escrito como XL (10
menos de 50), 41 como XLI, 42 como XLII, 43 como XLIII, y luego 44
como XLIV (10 menos de 50, luego 1 menos de 5).
Expresiones regulares
● Similarmente con 9, necesitamos sustraer
del siguiente caracter de mayor valor: 8
es VIII, pero 9 es IX (1 menos de 10), no
VIIII
● Ya que ningún caracter puede ser repetido
mas de tres veces
● 90 es XC mientras que 900 es CM
Expresiones regulares
● Los caracteres “cinco” no pueden ser repetidos. El número
10 siempre será representado por X, nunca por VV. El
número 100 será C, nunca LL
● Los Números romanos siempre son escritos de mayor a
menor y leidos de derecha a izquierda así que el orden de
los caracteres es muy importante. DC es 600 y CD es un
número completamente diferente (400, 100 menos de
500). CI es 101 y IC es ni siquiera un número válido (ya
que no puedes sustraer 1directamente de 100;
● Tendríamos que escribirlo XCIX, de 10 menos100, luego 1 menos
de 10).
Expresiones regulares
● Buscando coincidencias de los miles.
● Qué necesitaríamos para definir si un string
posee un número romano válido?
● Revisemos un digito a la vez ya que los
números romanos siempre están escritos de
mayor a menor
● Comencemos por el mayor: el caracter de los
miles
– Los números miles o mayores, se representan a
través de una serie de caracteres M
Expresiones regulares
>>> import re
>>> patron = '^M?M?M?$'
>>> re.search(patron, 'M')
<SRE_Match object at 0106FB58>
>>> re.search(patron, 'MM')
<SRE_Match object at 0106C290>
>>> re.search(patron, 'MMM')
<SRE_Match object at 0106AA38>
>>> re.search(patron, 'MMMM')
>>> re.search(patron, '')
<SRE_Match object at 0106F4A8>
Expresiones regulares
● Este patrón consiste de tres partes:
● ^ para coincidir lo que comience en el string. De no estar este
caracter, podría coincidir con cualquier lugar donde M esté
presente y no es lo que queremos ya que debemos asegurarnos
que el caracter mayor este al inicio.
● M? para opcionalmente coincidir algún caracter M. Como este es
repetido tres veces, estaremos coincidiendo de uno a tres
caracteres.
● $ para coincidir solo lo que termina en el string. Cuando lo
usamos junto al caracter ^ al inicio,significa que el patron debe
coincidir el string entero sin algo antes o después del caracter M
Expresiones regulares
● La escencia del módulo re es la función search() ya que
toma una expresión regular (patron) y un String ('M') y trata
de conseguir coincidencias.
● Si alguna es encontrada, search() retorna un objeto con
varios métodos que describen la coincidencia
● Si ninguna coincidencia se consigue, search() returna None
● Todo lo que nos importa ahora es saber si el patron coincide

● Lo que podemos hacer con solo ver el objeto ser retornado en


nuestra terminal
● 'M' coincide esta expresion regular ya que la primera M opcional
coincide y la segunda y tercera M opcionales son ignoradas
Expresiones regulares
● 'MM' coincide porque la primera y segunda M son
condicionales y la tercera M es ignorada
● 'MMM' coincide ya que se cumplen las tres condiciones
de M opcionales
● 'MMMM' no coincide. Todos los tres caracteres M
coinciden pero la expresión regular insiste en que
termine (por el caracter $), y el String aun continúa (por
la cuarta M) así que search retorna None.
● Como dato interesante, un String vacío coincide ya que
los tres caracteres son opcionales
Expresiones regulares
● Ahora, busquemos las centenas:
● Estas son mas dificiles que las centenas ya que hay
muchas formas en que estas deben ser representadas
dependiendo de su valor
– 100 = C
– 200 = CC
– 300 = CCC
– 400 = CD
– 500 = D
– 600 = DC
– 700 = DCC
– 800 = DCCC
– 900 = CM
Expresiones regulares
● Asi que tenemos cuatro patrones posibles:
● CM
● CD
● De cero a tres caracteres C
● D seguido de cero a tres caracteres D
● Los últimos dos patrones pueden ser
mezclados
– Un caracter opcional D seguido de cero a tres
caracteres C
Expresiones regulares
>>> import re
>>> patron = '^M?M?M?(CM|CD|D?C?C?C?)$'
>>> re.search(patron, 'MCM')
<SRE_Match object at 01070390>
>>> re.search(patron, 'MD')
<SRE_Match object at 01073A50>
>>> re.search(patron, 'MMMCCC')
<SRE_Match object at 010748A8>
>>> re.search(patron, 'MCMC')
>>> re.search(patron, ' ')
<SRE_Match object at 01071D98>
Expresiones regulares
● Este patrón comienza de la misma fortma que el
anterior, revisando al inicio del String (^), luego el lugar
de los caracteres de mil (M?M?M?).
● Luego vemos algo nuevo, los parentesis que define un
grupo de tres patrones mutuos separados por pipes:
CM, CD, y D?C?C?C? (que es una D opcional seguida de
cero a tres caracteres C opcionales)
● El análisis de la expresión regular busca por cada uno
de esos patrones en orden (de izquierda a derecha) y
toma el primero que coincide e ignora el resto
Expresiones regulares
● 'MCM' coincide porque la primera M
coincide y luego la segunda y tercera son
ignoradas
● CM coincide (por eso los patrones CD y D?
C?C?C? no llegan ni a ser considerados).
● MCM es la representación romana de
1900.
Expresiones regulares
● 'MD' coincide porque la primera M
coincide y la sengunda y tercera M son
ignoradas, y el patron D?C?C?C? coincide
con D (cada uno de los caracteres C
opcionales son también ignorados).
● MD es la representacion romana de 1500.
Expresiones regulares
● 'MMMCCC' coincide porque las tres M
coinciden y el patron D?C?C?C? Coincide
CCC (la D es opcional e ignorada)
● MMMCCC es la representación romana de
3300.
Expresiones regulares
● 'MCMC' no coincide. La primera M coincide pero la
segunda y tercera M son ignoradas,
● CM coincide pero el $ no coincide porque aun no
estamos al final del string
● Aun tenemos un caracter C sin coincidir
● C no coincide como parte del patron D?C?C?C?
porque el patron MC ya ha coincidido
● También, hara coincidencia un String vacio
Expresiones regulares
● Ahora tenemos otra opción y es la de definir la
cantidad de caracteres sin repetirlos utilizando las
llaves
>>> pattern = '^M{0,3}$'
>>> re.search(pattern, 'M')
<_sre.SRE_Match object at 0x008EEB48>
>>> re.search(pattern, 'MM')
<_sre.SRE_Match object at 0x008EE090>
>>> re.search(pattern, 'MMM')
<_sre.SRE_Match object at 0x008EEDA8>
>>> re.search(pattern, 'MMMM')
>>>
Expresiones regulares
● Y ahora revisemos las decenas y ahora es autoexplicativo :
>>> pattern = '^M?M?M?M?(CM|CD|D?C?C?C?)(XC|XL|L?X?X?X?)$'
>>> re.search(pattern, 'MCMXL')
<_sre.SRE_Match object at 0x008EEB48>
>>> re.search(pattern, 'MCML')
<_sre.SRE_Match object at 0x008EEB48>
>>> re.search(pattern, 'MCMLX')
<_sre.SRE_Match object at 0x008EEB48>
>>> re.search(pattern, 'MCMLXXX')
<_sre.SRE_Match object at 0x008EEB48>
>>> re.search(pattern, 'MCMLXXXX')
>>>
Expresiones regulares
● También, la expresión que detalla las
unidades es definida así:

'^M?M?M?(CM|CD|D?C?C?C?)(XC|XL|L?X?X?X?)(IX|IV|V?I?I?I?)
$'
Expresiones regulares
● Y con la definicion a través de cantidades
en llaves, como se vería?

'^M{0,3}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})
$'
PF
● Inclusive, es mas interesante aún cuando nos damos cuenta que el
operador lambda() tiene que retornar una expresion
● Ya que como hemos visto, las expresiones pueden contener bloques condicionales
>>> pr = lambda s:s
>>> namenum = lambda x: (x==1 and pr("one")) \
.... or (x==2 and pr("two")) \
.... or (pr("other"))

>>> namenum(1)
'one'
>>> namenum(2)
'two'
>>> namenum(3)
'other'
PF
● Sustituir los bucles (loops) es tan sencillo
como sustituir bloques de condicionales.
● for puede ser sustituido por map()

for e in lst: func(e) # Basado en


sentencias
map(func,lst) # Basado en map()
PF
# Creemos una funcion
do_it = lambda f: f()

# f1, f2, f3 (etc) recibiran la ejecución


map(do_it, [f1,f2,f3])
PF: Asignatura
● Modificar el script con programación
funcional
● Especificamente en:
● Bucle
● Condicional de argumentos
Python Avanzado:
PyGTK
PyGTK
● PyGTK es un conjunto de envoltorios
(wrappers) para las bibliotecas GTK+ de
interfaces de usuario (GUI)
● Ofrece un conjunto de elementos gráficos
para crear aplicaciones de escritorio
● Es parte del proyecto GNOME
PyGTK
● GObject es la clase base que provee los atributos en
comun y las funciones a las clases PyGTK
● ATK son las herramientas para mejoras en las
interfaces para los discapacitados
● GTK es el módulo de las interfaces
● Pango es la biblioteca de la internacionalización
● Cairo se utiliza para el desarrollo de gráficos 2D
● Glade es el constructor de GUIs a través de XML
PyGTK: Nuestros primeros
pasos
● Guardemos este código como center.py
#!/usr/bin/python
import gtk
class PyApp(gtk.Window):
def __init__(self):
super(PyApp, self).__init__()

self.connect("destroy", gtk.main_quit)
self.set_size_request(250, 150)
self.set_position(gtk.WIN_POS_CENTER)
self.show()

PyApp()
gtk.main()
PyGTK
● El ejemplo anterior muestra una ventana centrada en la
pantalla
import gtk
● Importa el módulo GTK. Ahora tenemos los objetos que crean
interfaces gráficas
class PyApp(gtk.Window):
● Creamos la clase PyApp. Esta hereda Window
def __init__(self):
super(PyApp, self).__init__()
● Este es el constructor que construye nuestra aplicacion.
También llama el constructor de la clase padre a través de la
llamada super()
PyGTK
self.connect("destroy", gtk.main_quit)
● Conectamos la señal “destroy” a la funcion
main_quit. La señal destroy es invocada cuando
se hace click en el botón de cerrar en la barra de
título o se ejecuta Alt F4
● Nota importante: La ventana esta siendo cerrada
pero a aplicación sigue ejecutandose en memoria
pero al ejecutar main_quit() cerramos la
aplicacion completamente
self.set_size_request(250, 150)
● Define el tamaño de la ventana de 250x150px
PyGTK
self.set_position(gtk.WIN_POS_CENTER)
● Coloca la ventana en el centro de la pantalla
self.show()
● Aquí mostramos la ventana. La ventana no es
visible hasta que llamemos el método show()
PyApp()
gtk.main()
● Creamos la instancia de nuestro programa e
iniciamos el bucle principal
PyGTK
● Ahora definiremos un ícono en la barra de titulo
#!/usr/bin/python
import gtk, sys
class PyApp(gtk.Window):
def __init__(self):
super(PyApp, self).__init__()
self.set_title("Icon")
self.set_size_request(250, 150)
self.set_position(gtk.WIN_POS_CENTER)
try:
self.set_icon_from_file("web.png")
except Exception, e:
print e.message
sys.exit(1)
self.connect("destroy", gtk.main_quit)
self.show()
PyApp()
gtk.main()
PyGTK
● Lo introducido en este código es:
self.set_title("Icon")
● Definimos el título de la ventana
● self.set_icon_from_file("web.png")
● Definimos el ícono desde un archivo
PyGTK
● Ahora en este ejemplo de dos partes, comenzaremos creando botones
#!/usr/bin/python
import gtk
class PyApp(gtk.Window):
def __init__(self):
super(PyApp, self).__init__()

self.set_title("Buttons")
self.set_size_request(250, 200)
self.set_position(gtk.WIN_POS_CENTER)

btn1 = gtk.Button("Button")
btn1.set_sensitive(False)
btn2 = gtk.Button("Button")
btn3 = gtk.Button(stock=gtk.STOCK_CLOSE)
btn4 = gtk.Button("Button")
btn4.set_size_request(80, 40)
PyGTK
● No olvidemos mantener la identación...

fixed = gtk.Fixed()
fixed.put(btn1, 20, 30)
fixed.put(btn2, 100, 30)
fixed.put(btn3, 20, 80)
fixed.put(btn4, 100, 80)
self.connect("destroy", gtk.main_quit)
self.add(fixed)
self.show_all()
PyApp()
gtk.main()
PyGTK
● En la nueva ventana mostramos cuatro
tipos diferentes de botones
btn1 = gtk.Button("Button")
● Un botón es un implemento hijo (child
widget) y estos deben ser siempre colocados
dentro de contenedores
btn1.set_sensitive(False)
● Hacemos este un botón inhabilitado.
Gráficamente este botón estará mas gris
PyGTK
btn3 =
gtk.Button(stock=gtk.STOCK_CLOSE)
● Este tercer botón muestra una imagen dentro
de su área. La biblioteca PyGTK tiene varias
imágenes predefinidas que podemos utilizar
– Nota: No son imágenes de confiar ya que en
muchas distribuciones, estas no aparecen
btn4.set_size_request(80, 40)
● Aqui le cambiamos el tamaño a los botones
PyGTK
fixed = gtk.Fixed()
● Fixed es un widget contenedor invisible. Su
proposito es tener únicamente widgets hijo
fixed.put(btn1, 20, 30)
fixed.put(btn2, 100, 30)
...
● Aquí colocamos los widgets dentro del
contenedor fixed
PyGTK
self.add(fixed)
● Definimos el contenedor
Fixed para que sea el
contenedor principal de
nuestro widget Window
self.show_all()
● Tenemos dos opciones,
utilizar show_all() para
mostrarlo todo o usar en
método show() en cada
uno de los widgets
PyGTK
● Los tooltips son pequeñas ayudas que se muestran en
ventanitas al ejercer una accion, generalmente la
accion hover que consiste en colocar el cursor sobre
algún objeto
● Utilicemos los tooltips:
import gtk
class PyApp(gtk.Window):
def __init__(self):
super(PyApp, self).__init__()
self.set_title("Tooltips")
self.set_size_request(250, 200)
self.set_position(gtk.WIN_POS_CENTER)
self.connect("destroy", gtk.main_quit)
self.fixed = gtk.Fixed()
self.add(self.fixed)
button = gtk.Button("Button")
button.set_size_request(80, 35)
self.fixed.put(button, 50, 50)
self.set_tooltip_text("Window widget")
button.set_tooltip_text("Button widget")
self.show_all()

PyApp()
gtk.main()
PyGTK
● En el pasado ejemplo le colocamos un
tooltip
self.set_tooltip_text("Window widget")
button.set_tooltip_text("Button widget")
● set_tooltip_text() hará el trabajo
PyGTK - Eventos
● Todas las aplicaciones de interfaces de
usuario son manejadas a través de
eventos y PyGTK no es la excepción
● Las aplicaciones se inician con el loop
principal (gtk.mail()) que continuamente
chequea por eventos recien generados
● Si no hay ningun evento, la aplicacion
espera y no hará nada
PyGTK - Eventos
● Los eventos son los mensajes desde el servidor X a
la aplicacion
● Cuando hacemos click en un botón, la señal será
emitida
● Estas señales son específicas del widget
● Usaremos los manejadores de señales (signal
handlers) para reaccionar ante estas.
● Estos handlers son llamados “callbacks”
● handler_id = button.connect("clicked", self.on_clicked)
PyGTK - Eventos
● En el ejemplo anterior usamos el método
connect() de la clase Gobject para
conectarn el callback on_clicked() con la
señal llamada clicked
● GtkButton es un objeto GObject
● El método connect returna un
identificador del manejador (handler id)
que es utilizado para univocamente
identificar el método callback
PyGTK - Eventos
● El identificador puede ser utilizado con los
siguientes métodos
def disconnect(handler_id)
def handler_disconnect(handler_id)
def handler_is_connected(handler_id)
def handler_block(handler_id)
def handler_unblock(handler_id)
PyGTK - Eventos
● Como reaccionar ante eventos y señales?
import gtk
class PyApp(gtk.Window):
def __init__(self):
super(PyApp, self).__init__()
self.set_title("Quit Button")
self.set_size_request(250, 200)
self.set_position(gtk.WIN_POS_CENTER)
self.connect("destroy", self.on_destroy)
fixed = gtk.Fixed()
quit = gtk.Button("Quit")
quit.connect("clicked", self.on_clicked)
quit.set_size_request(80, 35)
PyGTK - Eventos
fixed.put(quit, 50, 50)
self.add(fixed)
self.show_all()
def on_destroy(self, widget):
gtk.main_quit()

def on_clicked(self, widget):


gtk.main_quit()

PyApp()
gtk.main()
PyGTK - Eventos
self.connect("destroy", self.on_destroy)
● El método connect() une el método
on_destroy() a la señal destroy()
quit.connect("clicked", self.on_clicked)
● Al apretar el botón quit, la señal que le
hicimos click sera ejecutada. Cuando
hacemos click en el botón quit, llamamos al
método on_clicked
PyGTK - Eventos
def on_destroy(self, widget):
gtk.main_quit()
● En el método on_destroy() reaccionamos a la señal
destroy. Llamamos el metodo main_quit() que
termina la aplicación
def on_clicked(self, widget):
gtk.main_quit()
● Aquí en el método on_clicked() tomamos dos
parámetros. El parámetro widget es el objeto que
fue ejecutado por esta señal. En nuestro caso es el
botón quit

También podría gustarte