====== Python ======
//Sintaxis y uso básico del lenguaje.//
===== Básico =====
==== Sintaxis ====
=== Variables ===
a = 3 # Crea la variable numérica a con valor 3
b = 'abc' # Crea la variable string b con valor 'abc'
c = "def" # Crea la variable string b con valor 'def'
e = True # Crea una variable booleana e
del a # Elimina de memoria la variable a
a, b = 3, 4 # a = 3, b = 4
Pequeños tips en la asignación de variables:
a, b, c = 1, 2, 3 # Asignación de varios valores
a, b = b, a # Intercambio de valores
mensaje = "muchas visitas" if visitas_diarias>1400 else "pocas visitas" # Asignación condicional (operador ternario)
=== Condiciones ===
if i == 3:
print "i es 3"
else:
print "i no es 3"
show () if a == 1 else noshow()
=== Bucles ===
Para recorrer una lista de 0 a 10, por ejemplo, podemos hacer un foreach del array que devuelve la función ''range(0,10)'', aún así lo mejor es utilizar la función ''xrange(0,10)'' que no lo genera sino que devuelve el elemento a cada llamada.
for i in xrange(0,10):
print i
for _ in xrange(nplayers):
dplayer = {}
dplayer['id'] = buf.getInt()
dplayer['name'] = buf.getString()
players.append(dplayer)
my_container = ['Larry', 'Moe', 'Curly']
for el in my_container:
print el
my_container = ['Larry', 'Moe', 'Curly']
for index, element in enumerate(my_container):
print ('{} {}'.format(index, element))
Si en un bucle se llama a un ''break'' este devolverá ''False'' y, por lo tanto, puede añadirsele una clausula ''else'':
for email_address in user.get_all_email_addresses():
if email_is_malformed(email_address):
print ('Has a malformed email address!')
break
else:
print ('All email addresses are valid!')
=== Operadores ===
i ** 2 # eleva i a 2
i += 2 # suma 2 a i
i % 2 # el resto de i entre 2
=== Comentarios ===
# comentario de una línea
'''
comentario
de
varias
líneas
'''
=== Notas ===
No existe una función **main**, pero si queremos que un código se lance cuando se ejecute ese fichero (y no cuando se utilice como módulo) lo agregaremos dentro del siguiente if:
if __name__ == "__main__":
pass
Recoger parámetros pasados en la ejecución del script:
for arg in sys.argv:
print arg
* ''var1 is var2'' devuelve ''True'' si la referencia de ''var1'' es la misma que la de ''var2''.
==== Funciones ====
=== Función básica ===
def suma (a, b): # La llamaríamos como 'suma(3,5)', por ejemplo
return a + b
=== Parámetros con valores por defecto ===
def suma (a = 2, b = 4): # La podríamos llamar como 'suma(3,5)', como 'suma()', como 'suma(3)' o 'suma(b=5)'.
return a + b
=== Lista de parámetros ===
def testArgList(*args): # La podríamos llamar como "testArgList('aaa', 'bbb')" y...
print args[0] # Mostraría 'aaa'
print len(args) # Mostraría 2
print 'args:', args # Mostraría "args: ('aaa', 'bbb')"
=== Diccionario de parámetros ===
def testArgDir(**kwargs): # A esta la llamaríamos con un diccionario: "testArgDir(arg1='ccc', arg2='ddd')"....
print 'kwargs:', args # Mostraría "kwargs: {'arg1': 'ccc', 'arg2': 'ddd'}
# también podríamos llamarla: testArgDir(**{'arg1': 'ccc', 'arg2': 'ddd'})
=== Combinación de diccionario y lista ===
def generic (*args, **kwargs): # Si la llamamos como "generic(1, 'Africa', monty='python')"...
print args # Mostraría: "(1, 'Africa')"
print kwargs # Mostraría: "{'monty': 'python'}"
=== Almacenar funciones ===
def func (): pass
a = func
a()
=== Notas ===
El valor de una variable que se usa dentro de una función es tomado del ámbito donde se llama a dicha función, si no queremos que esto ocurra deberíamos declararla dentro de esta.
def suma ():
return x + 4
x = 4
suma() # Devolvería 8
Podemos omitir el retorno de una función utilizando ''_'':
(options, _) = parser.parse_args()
==== Decorators ====
Es una función que retorna otra función. Generalmente se aplican para realizar una transformación utilizando la sintaxis: ''@elemento''. \\
Son muy utilizadas en la orientación a objetos para indicar métodos estáticos y de clase. \\
Los siguientes métodos son equivalentes para la llamada de una función estática:
def f(...):
...
f = staticmethod(f)
@staticmethod
def f(...):
...
==== Colecciones ====
=== Tipos ===
Una **tupla** es una colección inmutable que no puede modificarse tras ser creada.
tupla = ("a", "b", "mpilgrim", "z", "example")
Las **listas** son los arrays de otros lenguajes.
lista = ["a", "b", (33, 44)]
Los **diccionarios** son colecciones de clave\valor.
dicci = { "a" : 1, "b" : 2 }
Los **sets** son conjuntos sin elementos repetidos:
my_set = {1, 2, 3}
=== Editar una colección ===
lista = ['Hola', 'Adios', 'Hasta luego'] # Crea una lista
lista[0] = 'ey!' # Cambia el primer elemento
print lista # Muestra la lista
lista.append('Nos vemos!') # Añade un elemento a la lista
len(lista) # Muestra el tamaño de la lista
del(lista[0]) # Elimina el primer elemento de la lista
lista.insert(2, 'Buenos días')
last_elem = lista.pop() # Asigna el último elemento a last_elem y lo elimina de la lista
=== Otras acciones sobre listas ===
* Concatenar listas: ''lista1 + lista1''
* Para saber si un elemento está o no en la lista usaremos la palabra clave ''in'':
if 1 in lista:
print "Existe!"
* Para ordenar una lista utilizaremos: ''sorted(l)''
* Saber el índice de un elemento en una lista: ''lst.index(e)''.
* Para recoger los elementos sin repeticiones de una lista haremos: ''set(l)''
* Para invertir los elementos de una lista haremos: ''reversed(l)''
* Para saber los elementos que están en ''s'' pero no en ''t'' haremos: ''set(s).difference(t)''
* Recoger el elemento más pequeño o más grande con ''min()'' y ''max()'' respectivamente.
* Sumar sus elementos con ''sum()''.
=== Acceso a una colección ===
Por su posición:
myList[3]
Cuando accedemos a los elementos de una colección a partir de sus índices podemos indicar números negativos, estos significarían, por ejemplo, ''colection[-1]'' el último elemento, ''colection[-2]'' el penultimo... \\
Recorrer una colección a partir de su indice:
for i in range(len(myList)):
myList[i]
Iterar los elementos de la colección:
for elem in myList:
print elem
Iterar en los elementos de un diccionario:
for key, value in d.iteritems():
Recoger un rango intermedio (del elemento 5 al 10):
myList2 = myList[5:10]
Podemos acceder a un //rango abierto//, por ejemplo la lista a partir del segundo elemento:
print lista[2:]
=== Propiedades de los sets ===
* Los sets son conjuntos de datos que no pueden tener elementos repetidos. Si se añade un elementos que ya exista en la lista este será ignorado.
* Para añadir elementos a un set se hace con su método ''add(elemento)''.
Sobre los sets podemos hacer las siguientes acciones:
* **Union**: se crea un set nuevo con los elementos de A y B: ''A | B''.
* **Intersección**: el nuevo set contiene los elementos que coinciden en A y B: ''A & B''
* **Diferencia**: los elementos que existen en A pero no en B: ''A - B''.
* **Diferencia simétrica**: elementos que sólo existen en un conjunto, A o B: ''A ^ B''.
def get_both_popular_and_active_users():
return (set(get_list_of_most_active_users()) & set(get_list_of_most_popular_users()))
=== Tuplas ===
Pueden ser usados para extraer datos de un array:
list_from_comma_separated_value_file = ['dog', 'Fido', 10, 'brown']
(animal, name, age, _) = list_from_comma_separated_value_file
output = ('{name} the {animal} is {age} years old'.format(animal=animal, name=name, age=age))
El carácter ''_'' se usa para "desestimar" un dato.
=== Propiedades de diccionarios ===
* El formato de la definición de un diccionario es: ''nombre = {clave : valor , clave : valor...}''. Luego para acceder a sus elementos sería con ''nombre[clave]''.
* Para acceder a las clabes: ''lista.keys()''.
* A los valores: ''lista.values()''.
* Y a ambos: ''lista.items()'' <- Devuelve una lista de dos dimensiones.
* Para agregar un nuevo elemento: ''lista["nuevoNombre"] = valor''
* Para saber si la clave existe mediante el método ''has_key()'' o con el ''in''.
* Puedes pasar un diccionario como argumentos ''**kwargs'' precediendole ''**''.
if lista.has_key(2):
pass
if 2 in lista:
pass
Para unir diccionarios...
x = {'a':1, 'b': 2}
y = {'b':10, 'c': 11}
z = dict(x.items() + y.items())
Para eliminar elemento de un diccionario...
del d['name']
Para crear un diccionario a partir de la función dict:
dict(akey='avalue', bkey=3)
Para recorrer clave\valor en los diccionarios:
for (k, v) in mydict.items():
print k, v
Para devolver un valor por defecto de un diccionario es mejor usar el método ''get'':
# Mal!
log_severity = None
if 'severity' in configuration:
log_severity = configuration['severity']
else:
log_severity = 'Info'
# Bien!
log_severity = configuration.get('severity', 'Info')
=== Notas ===
* Copiar una lista a otra: ''b[:] = a[:]''
* Podemos crear una pila a partir de los métodos ''append()'' y ''pop()''.
* Al añadir una lista a una lista se hace por referencia, es decir, si añadimos una lista a si misma, en el elemento perteneciente estará la misma lista con ese elemento perteneciente.... la historia interminable!!
* Podemos desordenar una lista haciendo ''random.shuffle(l)''.
* Podemos convertir otros tipos a tupla o lista haciendo ''list()'' o ''tuple()''. Como por ejemplo una lista a partir de una secuencia (p.ej. una tupla): ''list(getAllLines())''.
==== Características del lenguaje ====
=== Interacción con el usuario mediante la consola ===
value = raw_input("Sure?") # recoger lo introducido por consola después del mensaje 'Sure?'
ivalue = input("Number?") # recoger un integer introducido por consola por el usuario.
_ # contiene el último valor sacado por consola.
=== Conversiones ===
i = int(num) # to int
f = float(num) # to float
l = long(num) # to long
s = str(num) # to string
=== Sobrecarga de operadores ===
Para nuestros propios tipos podemos definir cómo actuarán según los operadores que utilicemos:
__add__ A+A
__sub__ A-A
__mul__ A*A
__rmul__ Si el operando de la derecha es un tipo primitivo, también existe __radd__, __rdiv__...
__div__ A/A
__neg__ -A
__mod__ A%B
__pow__ A**B
__and__ A&B
__or__ A|B
__xor__ A^B
__eq__ A==B
__ne__ A!=B
__gt__ A>B
__lt__ A=B
__le__ A<=B
__lshift__ A<>B
__contains__ A in B, A not in B
__pos__ +A
__inv__ ~A
__abs__ abs(A)
__len__ len(A)
__getitem__ A[i] def __getitem__(self, index):
__setitem__ A[i] = v
__delitem__ del A[i]
__getslice__ A[s:e]
__setslice__ A[s:e] = v
__delslice__ del A[s:e]
Un ejemplo de uso de estos:
def __add__(self, otro):
return Punto(self.x + otro.x, self.y + otro.y)
=== Otros ===
def F(): pass # Permite dejar una función vacía
class C: pass # Permite dejar una clase vacía
==== Funciones nativas ====
=== Numéricas ===
round(3.232, 1) # redondea 3.232 a un decimal
min(3,2) # devuelve el mínimo entre dos números
max(3,2) # devuelve el máximo entre dos números
cmp(x,y) # Devuelve un valor negativo si xy.
=== Carácteres ===
ord('9') # saber el código ASCII de un carácter
chr(57) # devuelve el carácter correspondiente al código ASCII
=== Generales ===
print a # imprime la variable a
print a, b, c # imprime la variable a, seguida de la b y de la c; pueden ser de tipos distintos
print 'a' 'b' # imprime 'ab'
print 'a', 'b' # imprime 'a b'
print 'a', # imprime 'a' pero no realiza el salto de línea
=== Para iteraciones ===
* ''any'': Indica si al menos un elemento de la iteración es ''True''.
* ''all'': Indica si todos los elementos de la iteración son ''True''.
==== Funciones y propiedades del intérprete ====
=== Funciones ===
* ''dir()'' devuelve una lista de elementos accesibles.
* ''dir(e)'' devuelve una lista de elementos accesibles a partir de ese elemento (funciones, clases...).
* ''help()'' devuelve la ayuda del entorno.
* ''help(e)'' devuelve la ayuda para un elemento (función, clase...).
* ''type(e)'' devuelve el tipo de un elemento.
* ''id(o)'' devuelve el identificador interno del objeto.
* ''del(o)'' elimina de la memoria el objeto.
* ''reload(mod)'' vuelve a cargar en memoria el módulo 'mod'.
* ''repr(o)'' devuelve la representación en string (la que se usa por consola) de o.
=== Propiedades ===
o.__class__ # devuelve la clase del objeto
===== Orientación a objetos =====
==== Clases ====
Podemos crear clases utilizando ''class''. \\
Los métodos de la clase son funciones que tienen como primer argumento ''self'' el cual, dentro del método, funcionará como una referencia al objeto desde donde se llama (''this'' en otros lenguajes). \\
''self'' también se usa para indicar propiedades de la clase. \\
class Prueba:
nPrueba = 0
def __init__ (self, nvalue = 1):
self.nPrueba = nvalue
def testMethod (self):
print self.nPrueba
p = Prueba ()
p.testMethod()
==== Métodos especiales en las clases ====
* ''__init__'': constructor.
* ''__doc__'': muestra la documentación de la clase.
* ''__str__'': el string devuelto cuando se llame a ''str(obj)''.
==== Herencia ====
Para indicar herencia entre clases utilizamos la sintaxis siguiente (donde ''claseB'' hereda de ''claseA''):
class claseA:
pass
class claseB (claseA):
pass
==== Decorators útiles ====
* ''@staticmethod'' es un método que no conoce nada de la clase (o instancia). Simplemente trata los argumentos que le han sido pasados (no es altamente necesario debido a que puede ser utilizada una función simple en su lugar).
* ''@classmethod'' es un método que se le pasa la clase con la que fue llamado (o la de la instancia) como pruimer argumento. Es útil para realizar un método factoría de la clase, puede ser utilizado para iterar sobre las subclases.
==== Clases New & Old Style ====
A partir de la versión 2.1 el intérprete se comporta de forma diferente cuando se hace herencia de ''object''. \\
Las clases que no hereden de ''object'' son denominadas old-style mientras que las que sí lo hacen new-style. \\
Cuando hacemos ''x.__class__'', siendo x una instancia de una clase old-style, se devolverá la clase, pero si hacemos ''type(x)'' se devolverá que es del tipo instancia. Si esta fuese una new-style devolvería lo mismo, la clase. \\
Las new-style añaden nuevos decoradores, permiten usar descriptores, metaclases...
===== Uso del lenguaje =====
==== Documentación ====
Para documentar una clase pondremos un string justo después de la definición de esta:
class Prueba:
"Esta es una clase de prueba"
...
==== Organización del código ====
=== Módulos ===
Un módulo es un archivo de código Python al cual queremos acceder desde otro ''scope''. Para acceder a él debemos importarlo, y para ello llamar a sus funciones: ''.()''. Por ejemplo tenemos el módulo ''modul'' con la función ''func''.
* Importación de ''modul'' y llamada a ''func'':
import modul
print modul.func(3, 4)
* Importación de varios módulos:
import modul1, modul2
* Importación únicamente de ''func'':
from modul import func
func(3, 4)
* Importación de todas las funciones de ''modul'':
from modul import *
print func(3, 4)
* Importar ''modul'' con otro nombre:
import modul as mod
print mod.func(3, 4)
* Volcar un módulo en una variable:
import types # Importamos módulo types
a = types # Volcamos types sobre a
print type(a) == a.ModuleType # a es del tipo módulo??
=== Paquetes ===
Un paquete es un directorio que contiene módulos, ha de tener, además, un fichero con nombre ''__init__.py'', este fichero puede estar vacío pero es aconsejable agregar los imports básicos. \\
Por ejemplo, con la siguiente estructura...
+ indicators
- averages.py
- stochastics.py
- __init__.py
example.py
... Añadiendo en el ''__init__.py'' lo siguiente:
from stochastics import Stochastic
Dentro de ''example.py'' podemos utilizar cualquiera de los siguientes imports:
from indicators import Stochastic
==== Excepciones ====
En este [[script:python:new:xtra#easier_to_ask_for_forgiveness_than_permission|enlace]] puedes encontrar cómo manejar adecuadamente las excepciones.
=== Captura de excepciones ===
Podemos capturar excepciones generales mediante los bloques ''try'' y ''except'':
try:
print a
except:
print "a"
Podemos capturar excepciones concretas, por ejemplo, una ''NameError'':
try:
print a
except NameError, e:
print e
=== Lanzar excepciones ===
Podemos lanzar las excepciones que queramos, para ello usaremos ''raise'': ''raise NameError''.
=== Excepciones propias ===
Podemos crear nuestras propias excepciones personalizadas, para ello deben de heredar de la clase ''RuntimeError'':
class MyError(RuntimeError):
def __init__(self, msg):
self.Msg = msg
def getMsg(self):
return self.Msg
Para capturarla el bloque sería algo parecido a:
try:
pass
except MyError, obj:
print 'Msg:', obj.getMsg()
=== Ejemplos ===
try:
raise Exception()
except:
print "Sorry:", sys.exc_type + ":", sys.exc_value
try:
raise Exception("Fallo!")
except:
print sys.exc_value
try:
import Image
except ImportError, exc:
raise SystemExit("PIL must be loaded to run this example")
===== Notas =====
==== Cómo ====
=== Saber el directorio del módulo actual ===
import os
path = os.path.dirname(__file__)
O de un módulo concreto:
import a_module
print a_module.__file__
=== Escribir por la consola de error ===
import sys
sys.stderr.write('Writing error!')
=== Detectar cuando sale el programa ===
Registraremos una función (''savecouter'') con atexit:
import atexit
atexit.register(savecounter)
También lo podemos hacer con un decorador en ''savecounter'': ''@atexit.register''. \\
''atexit'' no llamará cuando...
* El programa se acaba debido a un ''signal''.
* ''os._exit()'' se invoca directamente.
* Se lanza un error fatal en el intérprete.
=== Testear la sintaxis de un script ===
$ python -m py_compile script.py
=== Checkear el estilo de un script ===
* Mediante el script [[https://pypi.python.org/pypi/pep8|pep8.py]]
* Online, en: [[http://pep8online.com/]]
==== Errores ====
=== Confundir variables de clase con variables de objeto ===
class A:
value = []
a = A()
a.value.append(1)
b = A()
b.value.append(2)
print b.value # [1, 2]
=== Utilizar un mutable (lista, diccionario) como valor por defecto ===
def test (a=[]):
a.append(1)
print a
test() # [1]
test() # [1, 1]
test() # [1, 1, 1]
==== Notas ====
=== Utilizar una codificación específica dentro del script ===
Tendremos que agregar el siguiente código como primera o segunda línea del script:
# -*- coding: utf-8 *-*
Siendo ''utf-8'' la codificación usada, existen otras como ''latin-1'', ''big5''...
=== Script ejecutable en Linux ===
Tendremos que agregar como primera línea del script el siguiente código:
#!/usr/bin/python
=== Dividir una línea de código ===
print \
'Hola'
s = 'División de una'\
'variable string'
=== Python en Windows ===
* Si en windows quieres ejecutar un script en Python sin que se muestre la consola únicamente has de hacerlo ejecutandolo desde ''pythonw.exe'' en vez de desde el ''python.exe''. O cambiando su extensión de ''.py'' a ''.pyw''.
* En Windows puedes tener varias versiones de Python instaladas, para indicar cual de ellas es la de por defecto, al instalarla tendremos que hacer un //Register Extensions//.
=== Llamar un script en Python que usa un paquete en disco ===
$ PYTHONPATH=/foo/bar/baz python somescript.py somecommand
O desde dentro del código:
import sys
sys.path.append("/home/me/mypy")
=== Usar la función print ===
Debido a la aparición de Python 3 y la no retro-compatibilidad aparece el paquete //future// donde se pueden usar funciones de la versión 2.x en formato 3.x, por ejemplo ''print''. Para ello el primer ''import que hagamos será'':
from __future__ import print_function