$$ \def\CC{\bf C} \def\QQ{\bf Q} \def\RR{\bf R} \def\ZZ{\bf Z} \def\NN{\bf N} $$

Tutorial: Programación en Python y Sage

Autores: Florent Hivert < florent . hivert @ univ-rouen . fr >, Franco Saliola < saliola @ gmail . com >, et al.

Este tutorial es una introducción a la programación básica en Python y Sage, dirigido a lectores con conocimientos elementales de programación pero no familiarizados con el lenguaje de Python. No es un tutorial completo. Un tutorial más completo es el Tutorial de Python. La documentación de Python, y en particular la librería estándar, pueden ser también de utilidad.

This tutorial is an introduction to basic programming in Python and Sage, for readers with elementary notions of programming but not familiar with the Python language. It is far from exhaustive. For a more complete tutorial, have a look at the Python Tutorial. Also Python’s documentation and in particular the standard library can be useful.

Un tutorial más avanzado presenta las nociones de objetos y clases en Python.

Los siguientes son otros recursos para aprender Python:

Estructuras de datos

En Python, la asignación de tipos es dinámica; no hay declaración de variables como tal. La funcion type()devuelve el tipo de un objeto obj. Para convertir un objeto a un tipo typ escriba typ(obj) asi como en int("123"). El comando isinstance(ex, typ) devuelve True si la expresión ex es del tipo typ y False de lo contrario. Más específicamente, todo valor es una instancia de una clase , y no hay diferencias entre clases y tipos.

El símbolo = denota la asignación de valores a variables; no se debe confundir con ,== que denota igualdad matemática. La desigualdad se denota !=.

Los tipos estándar son bool, int, list, `tuple <https://docs.python.org/library/functions.html#tuple>$_, $$set$$, $$dict$$, $$str$$.

  • El tipo bool ( booleano ) tiene dos valores: True y False. Las operaciones booleanas se denotan por sus nombres or y``not.

  • Los tipos int y long de Python son usados para representar números enteros de tamaño limitado. Para manejar enteros arbitrariamente grandes con aritmética exacta, Sage usa su propio tipo, llamado `Integer <../reference/rings_standard/sage/rings/integer.html#sage.rings.integer.Integer>`_.

  • Una lista ( list ) es una estructura de datos que agrupa valores. Se construye usando corchetes como en [1, 3, 4]. La función `range() <https://docs.python.org/library/functions.html#range>`_ crea listas de enteros. También es posible crear listas usando comprensiones de listas: [ for in (if ) ]. Por ejemplo:


In [ ]:
[ i^2 for i in range(10) if i % 2 == 0 ]
  • Una tupla ( tuple) es muy similar a una lista; se construye usando paréntesis. La lista vacía se denota mediante () o mediante la construcción `tuple <https://docs.python.org/library/functions.html#tuple>$_. Si una tupla tiene un solo elemento, se debe escribir $$(a,)$`. Una tupla es inmutable (no se puede cambiar) pero es enumerable (hashable - ver abajo). También es posible crear tuplas usando comprensiones de listas:

In [ ]:
tuple(i^2 for i in range(10) if i % 2 == 0)

Un conjunto ( set) es una estructura de datos que contiene valores sin multiplicidad u orden. Se crea a partir de una lista (o cualquier iterable) con el constructor set . Los elementos de un conjunto deben ser enumerables (hashable):


In [ ]:
set([2,2,1,4,5])

In [ ]:
set([ [1], [2] ])
  • Un diccionario ( dictionary) es una tabla de asociaciones, que asocia valores a claves. Las claves deben ser enumerables (hashable). Se crean los diccionarios usando el constructor dict, o usando la sintaxis:

In [ ]:
{ clave1 : valor1, clave2 : valor2 ...}

Por ejemplo:


In [ ]:
age = {'toto' : 8, 'mom' : 27}; age
  • Las comillas (simples ' ' o dobles " ") delimitan cadenas de caracteres. Se pueden concatenar usando \+.
  • Para listas, tuplas, cadenas y diccionarios, el operador de indexado se escribe l[i]. También es posible sacar " tajadas " ( slices )de listas, tuplas y cadenas, l[:], l[:b], l[a:], or l[a:b]. Indices negativos empiezan por el final.
  • La función len() https://docs.python.org/library/functions.html#len devuelve el numbero de elementos de una lista, tupla, conjunto, cadena o diccionario.Se escribe x in C para verificar si x está en C.
  • Por último, hay un valor especial para denotar la ausencia de un valor llamado None.

Estructuras de control

En Python no hay delimitador para el comienzo y el final de un bloque de instrucciones. Los bloques son delimitados solamente mediante sangrías (indentation). Por lo general un bloque nuevo se introduce mediante :. Python posee las siguientes estructuras de control:

  • Instrucción condicional

In [ ]:
a = 1

In [ ]:
if a == 1:
    print "yes"

In [ ]:
if a == 2:
    print "no"
else:
    print "yes"

In [ ]:
if a == 2:
    print "no"
elif a == 1:
    print "yes"
else:
    print "no"
  • Instrucciones iterativas:

In [ ]:
l = [1,2,3,4,5]

In [ ]:
for v in l:
    print v

In [ ]:
i = 1
while i < 500:
    print i
    i = i*2
  • En un bucle, continue salta a la siguiente iteración.
  • Un iterable es un objeto sobre el cual se puede iterar. Algunos tipos iterables son listas, tuplas, diccionarios y cadenas.

Funciones

Nota: funciones de Python vs. funciones matemáticas

En lo que sigue trabajaremos con funciones en el sentido de lenguajes de la programación. Las funciones matemáticas, así como se manipulan en cálculo, son manejadas por Sage en una forma diferente. En particular, no tiene sentido hacer manipulaciones matemáticas como la adición o la diferenciación en funciones de Python.

Se define una función usando la llave def :


In [ ]:
def myfunction(a):
    return a*a

In [ ]:
myfunction(4)

El resultado de una función se genera mediante la instrucción return. Las funciones muy cortas pueden crearse anónimamente, usando lambda (observe que no hay instrucción return):


In [ ]:
myfunction = lambda x: x*x

In [ ]:
myfunction(4)

Nota: programación funcional

Las funciones son objectos como cualquier otro. se pueden asignar a variables o devolver en una definicion. Para detalles vea el tutorial sobre Functional Programming for Mathematicians.

Ejercicios

Listas

Creación de listas I: [corchetes cuadrados]

Ejemplo:


In [ ]:
L = [3, Permutation([5,1,4,2,3]), 17, 17, 3, 51]
L

Ejercicio: Cree la lista [63,12,−10,"a",12], asígnela a la variable L e imprímala


In [ ]:
# editar aquí

Ejercicio: cree la lista vacía (se usa frecuentemente)


In [ ]:
# editar aquí

Creación de listas II: rango

La función range() https://docs.python.org/library/functions.html#range (rango) es una forma sencilla de construir listas de enteros. Esta es una traducción de la documentación de la función `range() https://docs.python.org/library/functions.html#range :

range([inicio,] fin[, paso])


In [ ]:
range(10)

In [ ]:
range(3,10)

In [ ]:
range(4,10,2)

Devuelve una lista que contiene una progresión aritmética de enteros.

range(i,j) devuelve $\[i,i+1,ldots,j-1\]$ el valor por defecto de start (!) es 0.

Cuando se ingresa un valor en paso, se especifica el incremento (o decremento)

Por ejemplo, range(4) devuelve $\[0, 1, 2, 3\]$. El punto final es omitido!

Estos números coinciden con los indices válidos para una lista de

4 elementos

Ejercicio: use range() https://docs.python.org/library/functions.html#range para construir la lista $[1, \ldots, 50]$


In [ ]:
# editar aquí

Ejercicio: use para construir la lista de numeros enteros entre el 1 y el 100 (inclusive)


In [ ]:
# editar aquí

El argumento step del comando`range() https://docs.python.org/library/functions.html#range puede ser negativo. Use range() para construir la lista $[10, 7, 4, 1, -2]$


In [ ]:
# editar aquí

Ver también:

  • `xrange() <https://docs.python.org/library/functions.html#xrange>`_ : devuelve un iterador en lugar de construir una lista.
  • `srange() <../reference/misc/sage/arith/srange.html#sage.arith.srange.srange>`_ : similar a range pero con enteros de Sage; ver abajo.
  • `xsrange() <../reference/misc/sage/arith/srange.html#sage.arith.srange.xsrange>`_ : similar a xrange pero con enteros de Sage.

Creación de listas III: comprensiones de listas

Las comprensiones de listas son una forma concisa de crear listas a partir de otras listas (u otros tipos de datos).

Ejemplo: ya sabemos como crear la lista $[1,\ldots, 16]$ :


In [ ]:
range(1,17)

Usando una comprensión de lista, a ahora podemos crear la lista $[1^2, 2^2, \ldots , 16^2]$


In [ ]:
[i^2 for i in range(1,17)]

In [ ]:
sum([i^2 for i in range(1,17)])

Ejercicio: [ Projecto Euler, Problema 6 ]

La suma de los primeros 10 números naturales es:

$$1^2+2^2+\ldots+10^2=385$$

El cuadrado de la suma de los primeros 10 números naturales es:

$$(1+2+\ldots + 10)^2 = 3025$$

La diferencia entre estos números es:

$$3025-385=2640$$

Encuentre la diferencia entre la suma de los cuadrados de los primeros 100 números y el cuadrado de la suma.


In [ ]:
# editar aquí

In [ ]:
# editar aquí

In [ ]:
# editar aquí

In [ ]:
[p^2 for p in [1,2,..,100] if is_prime(p)]

Ejercicio: Use una comprensión de lista para listar todos los números naturales menores que 20 que son múltiplos de 3 o 5. Pista:

  • Para obtener el residuo de 7 dividido entre 3 use 7%3 .

  • Para verificar la igualdad use dos signos igual( == ); por ejemplo, 3 == 7 .

Projecto Euler, Problema 1 : Encuentre la suma de todos los múltiplos de 3 o 5 menores o iguales que 1000.


In [ ]:
# editar aquí

In [ ]:
[(x,y) for x in range(5) for y in range(3)]

In [ ]:
[[i^j for j in range(1,4)] for i in range(6)]

In [ ]:
matrix([[i^j for j in range(1,4)] for i in range(6)])

Exercise:

  1. Una tripla pitagórica es una tripla $(x,y,z)$ de enteros positivos que satisfacen $x^2+y^2=z^2$. Las triplas pitagóricas cuyos componentes son a lo sumo 10 son:
$$[(3,4,5),(4,3,5),(6,8,10),(8,6,10)].$$

In [ ]:
# editar aquí

In [ ]:
# editar aquí

In [ ]:
# editar aquí

Cómo acceder a los elementos individuales de una lista?

Para acceder a un elemento de una lista, use la sintaxis L[i], dondei es el índice del elemento.

Ejercicio:

  • Construya la lista L = [1,2,3,4,3,5,6] . Qué es L[3] ?

In [ ]:
# editar aquí
  • Qué es L[1] ?

In [ ]:
# editar aquí
  • Cuál es el índice del primer elemento de L ?

In [ ]:
# editar aquí
  • Qué es L [\-1] ? qué es L [\-2] ?

In [ ]:
# editar aquí
  • Qué es L.index(2) ? qué es L.index(3) ?

In [ ]:
# editar aquí

Modificación de listas: cambiar los elementos de una lista

Para cambiar el ítem en la posición i de una lista L :


In [ ]:
L = ["a", 4, 1, 8]
L

In [ ]:
L[2] = 0
L

Modificación de listas: añadir (append), extender (extend)

Para añadir un objeto a una lista:


In [ ]:
L = ["a", 4, 1, 8]
L

In [ ]:
L.append(17)
L

Para extender una lista con otra lista:


In [ ]:
L1 = [1,2,3]
L2 = [7,8,9,0]
print L1
print L2

In [ ]:
L1.extend(L2)
L1

Modificación de listas: invertir (reverse), sortear (sort), ...


In [ ]:
L = [4,2,5,1,3]
L

In [ ]:
L.reverse()
L

In [ ]:
L.sort()
L

In [ ]:
L = [3,1,6,4]
sorted(L)

In [ ]:
L

Concatenación de listas

Para concatenar dos listas, súmelas con el operador \+. Esta no es una operación conmutativa!


In [ ]:
L1 = [1,2,3]
L2 = [7,8,9,0]
L1 + L2

Se puede tajar una lista usando la sintaxis L[start : stop : step]. Esto devolverá una sublista de L.

Ejercicio: A continuación hay algunos ejemplos de tajadas de listas. Intente adivinar el resultado antes de evaluar la celda:


In [ ]:
L = range(20)
L

In [ ]:
L[3:15]

In [ ]:
L[3:15:2]

In [ ]:
L[15:3:-1]

In [ ]:
L[:4]

In [ ]:
L[:]

In [ ]:
L[::-1]

Ejercicio (Avanzado): La siguiente función combina un bucle con algunas de las operaciónes sobre listas mencionadas hasta ahora. Qué hace la función?


In [ ]:
def f(number_of_iterations):
    L = [1]
    for n in range(2, number_of_iterations):
        L = [sum(L[:i]) for i in range(n-1, -1, -1)]
    return numerical_approx(2*L[0]*len(L)/sum(L), digits=50)

In [ ]:
# editar aquí

Tuplas

Una tupla (tuple) es una lista inmutable . Es decir, no se puede modificar una vez se ha creado. Esto es útil para la seguridad del código, y sobre todo porque hace que las tuplas sean enumerables hashable) . Para crear una tupla, use paréntesis en lugar de corchetes:


In [ ]:
t = (3, 5, [3,1], (17,[2,3],17), 4)
t

Para crear una tupla con un solo elemento, se requiere una coma para eliminar la ambigüedad:


In [ ]:
(1)

In [ ]:
(1,)

Podemos crear una tupla a partir de una lista y viceversa:


In [ ]:
tuple(range(5))

In [ ]:
list(t)

Las tuplas se comportan como las listas en muchos respectos:

Operación Sintaxis para listas Sintaxis para tuplas
Acceder a un elemento list[3] tuple[3]
Concatenación list1 \+ list2 tuple1 \+ tuple2
Tajado list[3:17:2] tuple[3:17:2]
Copia inversa list[::\-1] tuple[::\-1]
Longitud len(list) len(tuple)

No es posible modificar una tupla:


In [ ]:
t = (5, 'a', 6/5)
t

In [ ]:
t[1] = 'b'

Generadores

Las “comprensiones de tuplas” no existen. En lugar de eso, la sintaxis produce algo llamado un generador. Un generador permite procesar una secuencia de ítems uno a la vez. Cada ítem se crea cuando se necesita y después se elimina. Esto puede ser bastante eficiente si cada ítem debe ser usado solo una vez.


In [ ]:
(i^2 for i in range(5))

In [ ]:
g = (i^2 for i in range(5))
g[0]

In [ ]:
[x for x in g]

g ahora está vacía.


In [ ]:
[x for x in g]

Un truco pitónico chévere es usar generadores como argumentos de funciones. No necesitamos doble paréntesis para esto.


In [ ]:
sum( i^2 for i in srange(100001) )

Diccionarios

Un diccionario es otro tipo de datos incorporado. A diferencia de las listas, que son indexadas por un rango de números que empiezan en 0, los diccionarios son indexados por llaves, que pueden ser cualquier objeto inmutable. Las cadenas de texto y los números siempre pueden usarse como llaves (porque son inmutables). En otros lenguajes de programación, a veces se llama a los diccionarios "arreglos asociativos"

Hay varias formas de definir diccionarios. Un metodo es usando llaves (corchetes redondos), {}, con entradas separadas por comas escritas como llave:valor :


In [ ]:
d = {3:17, 0.5:[4,1,5,2,3], 0:"goo", 3/2 : 17}
d

Otro método es usando el constructor dict, que admite una lista (o cualquier iterable) de 2-tuplas (llave, valor) :


In [ ]:
dd = dict((i,i^2) for i in xrange(10))
dd

Los diccionarios se comportan como listas y tuplas en varias operaciones importantes.

Operación Sintaxis para listas Sintaxis para diccionarios
Acceder elementos list[3] D["key"]
Longitud len(list) len(D)
Modificación L[3] = 17 D["key"] = 17
Eliminación de elementos del L[3] del D["key"]

In [ ]:
d[10]='a'
d

Un diccionario puede tener el mismo valor repetido varias veces, pero cada llave debe aparecer solo una vez y debe ser inmutable:


In [ ]:
d = {3: 14, 4: 14}
d

In [ ]:
d = {3: 13, 3: 14}
d

In [ ]:
d = {[1,2,3] : 12}

Otra forma de adicionar elementos a un diccionario es con el método update() , que actualiza el diccionario a partir de otro diccionario:


In [ ]:
d = {}
d

In [ ]:
d.update({10 : 'newvalue', 20: 'newervalue', 3: 14, 0.5:[1,2,3]})
d

Podemos iterar sobre las llaves, los valores, o ambos de un diccionario. Observe que internamente no se realiza ningún sorteo de las llaves. En general, el orden de las llaves/valores dependerá en localizaciones en memoria, y difiere entre computadores diferentes y/o ejecuciones en el mismo computador. Al imprimir, Sage sortea las entradas del diccionario por llaves, específicamente para hacer los resultados más reproducibles. Sin embargo, los métodos keys() y values() no sortean. Si que su salida sea reproducible, debe sortearla primero, como en los ejemplos a continuación:


In [ ]:
d = {10 : 'newvalue', 20: 'newervalue', 3: 14, 0.5:(1,2,3)}

In [ ]:
sorted([key for key in d])

In [ ]:
d.keys()   # random order

In [ ]:
sorted(d.keys())

In [ ]:
d.values()   # random order

In [ ]:
set(d.values()) == set([14, (1, 2, 3), 'newvalue', 'newervalue'])

In [ ]:
d.items()    # random order

In [ ]:
sorted([(key, value) for key, value in d.items()])

Ejercicio: Considere el siguiente grafo dirigido.

Cree un diccionario cuyas llaves son los vértices de éste grafo, y cuyos valores son las listas de vertices a los que el vértice apunta. Por ejemplo, el vertice 1 apunta a los vértices 2 y 3, así que el diccionario tiene la forma:


In [ ]:
d = {  ..., 1:[2,3], ... }

In [ ]:
# editar aquí

Después intente:


In [ ]:
g = DiGraph(d)
g.plot()

Uso de tipos de Sage: El comando srange

Ejemplo: Construya una matriz $(3\times 3)$ cuya entrada $(i,j)$ es el número racional $(i,j)$. Los enteros generados por `range() son int ‘s de Python. Como consecuencia, al dividirlos se hace división euclídea:


In [ ]:
matrix([[ i/j for j in range(1,4)] for i in range(1,4)])

Por otra parte, dividir un Entero http://doc.sagemath.org/html/en/reference/rings_standard/sage/rings/integer.html de Sage por un Entero de Sage produce un número racional:


In [ ]:
matrix([[ i/j for j in srange(1,4)] for i in srange(1,4)])

La modificación de listas tiene sus consecuencias!

Intente producir los resultados de los siguientes comandos:


In [ ]:
a = [1, 2, 3]
L = [a, a, a]
L

In [ ]:
a.append(4)
L

Ahora intente:


In [ ]:
a = [1, 2, 3]
L = [a, a, a]
L

In [ ]:
a = [1, 2, 3, 4]
L

In [ ]:
L[0].append(4)
L

Esto es conocido como el efecto referencia. Se puede usar el comando deepcopy() https://docs.python.org/library/copy.html#copy.deepcopy para evitar este efecto:


In [ ]:
a = [1,2,3]
L = [deepcopy(a), deepcopy(a)]
L

In [ ]:
a.append(4)
L

El mismo efecto ocurre con diccionarios:


In [ ]:
d = {1:'a', 2:'b', 3:'c'}
dd = d
d.update( { 4:'d' } )
dd

Bucles y funciones

Para una explicación más charlada de esto, una buena referencia es esta seccion del tutorial de Python: http://docs.python.org/tutorial/controlflow.html http://docs.python.org/tutorial/controlflow.html

Bucles while

Los bucles while no se usan tanto como los bucles for en código de Python:


In [ ]:
i = 0
while i < 10:
    print i
    i += 1

In [ ]:
i = 0
while i < 10:
    if i % 2 == 1:
        i+=1
        continue
    print i 
    i+=1

Observe que el valor de verdad de la expresión de cláusula en el bucle while se evalua usando bool :


In [ ]:
bool(True)

In [ ]:
bool('a')

In [ ]:
bool(1)

In [ ]:
bool(0)

In [ ]:
i = 4
while i:
    print i
    i -= 1

Bucles for

A continuación hay un bucle for básico que itera sobre todo los elementos en la listal :


In [ ]:
l = ['a', 'b', 'c']
for letter in l:
    print letter

La función range() https://docs.python.org/library/functions.html#range es muy útil cuando desea generar progresiones aritméticas para recorrer en un bucle. Observe que el punto final nunca se incluye:


In [ ]:
range?

In [ ]:
range(4)

In [ ]:
range(1, 5)

In [ ]:
range(1, 11, 2)

In [ ]:
range(10, 0, -1)

In [ ]:
for i in range(4):
    print i, i*i

Para saltar inmediatamente al siguiente paso en la iteración, se usa la palabra continue:


In [ ]:
for i in range(10):
    if i % 2 == 0:
        continue
    print i

Para salir del bucle, use el comando break


In [ ]:
for i in range(10):
    if i % 2 == 0:
        continue
    if i == 7:
        break
    print i

Si necesita registrar la posición en la lista y su valor, una forma de hacerlo (no muy elegante) es así:


In [ ]:
l = ['a', 'b', 'c']
for i in range(len(l)):
    print i, l[i]

Una forma más limpia es usando enumerate() https://docs.python.org/library/functions.html#enumerate , que provee tanto el índice como el valor:


In [ ]:
l = ['a', 'b', 'c']
for i, letter in enumerate(l):
    print i, letter

Los bucles for funcionan el protocolo de iteración de Python. Esto permite hacer bucles sobre diversas clases de objetos. Por ejemplo:


In [ ]:
for i in GF(5):
    print i, i*i

Cómo funciona esto?


In [ ]:
it = iter(GF(5)); it

In [ ]:
next(it)

In [ ]:
next(it)

In [ ]:
next(it)

In [ ]:
next(it)

In [ ]:
next(it)

In [ ]:
next(it)

In [ ]:
R = GF(5)
R.__iter__??

El comando yield es una forma muy conveniente de producir iteradores. Más adelante veremos más al respecto.

Ejercicios

Para cada uno de los siguientes conjuntos, construya una lista con sus elementos y compute su suma. Use dos formas diferentes, si es posible: con un bucle y con una comprensión de lista.

  • Los primeros términos de la serie armónica:
$$\sum_{i=1}^n \frac{1}{i}$$

In [ ]:
# editar aquí
  • Los enteros impares entre $1$ y $n$.

In [ ]:
# editar aquí
  • Los primeros $n$ números impares.

In [ ]:
# editar aquí
  • Los números de $1$ a $n$ que no son divisibles por 2, por 3 ni por 5.

In [ ]:
# editar aqui

Los primeros $n$ enteros que no son divisibles por 2, por 3 ni por 5.


In [ ]:
# editar aquí

Funciones

Las funciones se definen usando la sentencia def , y los valores son devueltos usando la instrucción return :


In [ ]:
def f(x):
    return x*x

In [ ]:
f(2)

Las funciones pueden ser recursivas:


In [ ]:
def fib(n):
    if n <= 1:
        return 1
    else:
        return fib(n-1) + fib(n-2)

In [ ]:
[fib(i) for i in range(10)]

Las funciones son objetos de primera clase como cualquier otro. Por ejemplo, se pueden pasar como argumentos a otras functiones:


In [ ]:
f

In [ ]:
def compose(f, x, n):   # computa f(f(...f(x)))
    for i in range(n):
        x = f(x)        # este cambio es local en esta llamada de la función!
    return x

In [ ]:
compose(f, 2, 3)

In [ ]:
def add_one(x):
    return x + 1

In [ ]:
compose(add_one, 2, 3)

Se pueden definir valores por defecto para argumentos de funciones:


In [ ]:
def add_n(x, n=1):
    return x + n

In [ ]:
add_n(4)

In [ ]:
add_n(4, n=100)

In [ ]:
add_n(4, 1000)

Una función puede devolver múltiples valores:


In [ ]:
def g(x):
    return x, x*x

In [ ]:
g(2)

In [ ]:
type(g)

In [ ]:
a,b = g(100)

In [ ]:
a

In [ ]:
b

Es posible definir funciones con un número variable de argumentos y argumentos keyword:


In [ ]:
def h(*args, **kwds):
    print type(args), args
    print type(kwds), kwds

In [ ]:
h(1,2,3,n=4)

Usemos la instrucción yield para hacer un generador de los números de Fibonacci hasta el número $n$ :


In [ ]:
def fib_gen(n):
    if n < 1:
        return
    a = b = 1
    yield b
    while b < n:
        yield b
        a, b = b, b+a

In [ ]:
for i in fib_gen(50):
    print i

Ejercicios

  1. Escriba una función is_even , que devuelve True si n es par y False de lo contrario.
  2. Escriba una función every_other , que recibe una lista l como argumento y devuelve una lista con los elementos intercalados de l (uno sí y el siguiente no).
  3. Escriba un generador every_other , que recibe un iterable l como entrada y devuelve los elementos de l intercalados, uno después del otro.
  4. Escriba una función que computa el $n$-ésimo número de Fibonacci. Trate de mejorar el rendimiento.

In [ ]: