Apuntes_Python/01_curso/Modulo_1
2024-01-16 12:23:41 -03:00
..
__init__.py init Apuntes Python 2022-12-24 22:41:20 -03:00
1-1_primeros_pasos.py init Apuntes Python 2022-12-24 22:41:20 -03:00
1-2a_tipos_datos.py init Apuntes Python 2022-12-24 22:41:20 -03:00
1-2b_libreria_math.py init Apuntes Python 2022-12-24 22:41:20 -03:00
1-3a_condicionales.py init Apuntes Python 2022-12-24 22:41:20 -03:00
1-3b_funciones.py init Apuntes Python 2022-12-24 22:41:20 -03:00
1-3c_expresiones_lambda.py init Apuntes Python 2022-12-24 22:41:20 -03:00
1-3d_cadena_de_txt_de_documentacion.py init Apuntes Python 2022-12-24 22:41:20 -03:00
1-4a_if_for_range_while.py init Apuntes Python 2022-12-24 22:41:20 -03:00
1-4b_brake-else-continue.py init Apuntes Python 2022-12-24 22:41:20 -03:00
1-4c_entorno_virtual.py init Apuntes Python 2022-12-24 22:41:20 -03:00
1-4d_import_modulos_paquetes.py init Apuntes Python 2022-12-24 22:41:20 -03:00
1-4e_iteradores.py init Apuntes Python 2022-12-24 22:41:20 -03:00
1-4f_debugger.py init Apuntes Python 2022-12-24 22:41:20 -03:00
1-4g_actividad_evaluada.py init Apuntes Python 2022-12-24 22:41:20 -03:00
1-5_evaluacion_dados.py init Apuntes Python 2022-12-24 22:41:20 -03:00
fibo.py init Apuntes Python 2022-12-24 22:41:20 -03:00
README.md ed: domain links on files <kickto.net >letz.dev 2024-01-16 12:23:41 -03:00

Ir a: Repositorio, Modulo 2

Modulo 1 - Python basico

Indice

Primeros Pasos

Hola Mundo!

print("Hola Mundo")

Entrada de usuario

nombre = input("Ingresa tu nombre: ")
print("Hola", nombre, "!")

Ejemplo fibo

# Serie de Fibonacci: La suma de dos elementos define el sgte.
a, b = 0, 1
while b < 10:
	print(b, end=', ')
	a, b = b, a+b

Print básico

a = input("ingresa un número: ")
b = input("ingresa otro número: ")
a = int(a)
b = int(b)
c = a * b
print("La Multiplicación de los números",a,"y",b,"es",c)


a = input("ingresa un número: ")
b = input("ingresa otro número: ")
a = int(a)
b = int(b)
c = a + b
print("La SUMA de los números",a,"y",b,"es ",c)

Operaciones aritméticas

Division sin resto //

4//3 
# 1

Resto %

4%3
# 1

Potencia **

# 5 al cuadrado
5 ** 2

# 2 a la potencia de 7
2 ** 7

Última expresion _

1+3
# 4

3 + _
# 7

Redondeo round("número", "decimales")

round(8.6786346, 1)
# 8.7

Además de int y float, Python soporta otros como Decimal y Fraction, además tiene soporte integrado para números complejos.

usa j o J para indicar la parte imaginaria, ej.
3+5+j

Strings

Cadena Cruda r'cadena'

print(r'C:\\algun\directorio')
        
print('\t',r'~/Documentos')

print("""...\
     Fin de linea
        es automatico
        puedes evitarlo con \\
""")

Las cadenas de texto pueden ser operadas con + y \

3 * 'al' + 'mendra'
#   'alalalmendra'

palabra = 'Python'

palabra[0]
# 'P'

palabra[5]
#'n'

# último caracter
palabra[-1]
#   'n'

# penúltimo caracter
palabra[-2] 
#   'o'

palabra[-6]
# 'P'

# caracteres desde pos 0 (incluida) a 2 (exluida)
palabra[0:2]
# 'Py'

# caracteres desde pos 2 (incluida) a 5 (exluida)
palabra[2:5]
# 'tho'

palabra[:2] + palabra[2:]
# 'Python'

palabra[:4] + palabra[4:]
# 'Python'

len(palabra)
# 6

Listas

# definir
cuadrados = [1, 4, 9, 16]

# sumar listas
cuadrados + [36, 49, 64, 81, 100]

# modificar lista
cubos = [1, 8, 27, 65, 125 ]    # cubos[3] debiera ser 64
cubos[3] = 64

# Agregar el cubo de 6
cubos.append(216)
# y el cubo de 7
cubos.append(7 ** 3)
letras = ['a', 'b', 'c', 'd', 'e', 'f', 'g']

# reemplazar algunos valores
letras[2:5] = ['C', 'D', 'E']

# borrarlas
letras[2:5] = []

# reemplazar los elementos por una lista vacia
letras[:]

# Largo( lista )
len(letras)

# Listas agurapdas
a = ['a', 'b', 'c']
n = [1, 2, 3]
x = [a, n]

x           # [['a', 'b', 'c'], [1, 2, 3]]
x[0]        # ['a', 'b', 'c']
x[0][1]     # 'b'

1-1_primeros_pasos.py


Tipos de Datos

Consola python: python -i

>>> type(8)
<class 'int'>

>>> type(10.5)
<class 'float'>

>>> type(True)
<class 'bool'>

>>> type('hola')
<class 'str'>

>>> type(3+4j)
<class 'complex'>

Variables

  • Tipado dinámico
  • CaseSensitive
>>> numero = 4
>>> type(numero)
<class 'int'>

>>> numero = 4.5
>>> type(numero)
<class 'float'>

>>> nada = None
>>> type(nada)
<class 'NoneType'>

Expresiones:

  • 1 + 1 : Expresión que combina dos valores y un operador.

  • numero + 1 : Expresión que combina una variable, un valor y un operador.

Operadores:

  • Unarios y Binarios, que requieren uno o dos operandos.
    • Operadores Aritmeticos: + - * / // % **
    • Operadores Asignación: = += -= *= /= //= %= **=
    • Operadores Comparación: == != < <= > >=
    • Operadores Lógicos: and or not

Ejemplos operadores de comparación

Ejm. op. Resultado
1 == 1 True
1 != 1 False
1 > 2 False
2 > 3 False
1 >= 1 True
2 <= 3 True
a == b False
a != b True
a < b True
1 < 2 < 3 True

Tablas de Verdad

and

Var. A Op. Var. B Resultado
True and True True
True and False False
False and True False
False and False False

or

Var. A Op. Var. B Resultado
True or True True
True or False True
False or True True
False or False False

not

Op. Var. Resultado
not True False
not False True

Precedencia de operadores

Orden Predecendencia Operadores
1 **
2 *, /, %, //
3 +, -
4 <=, <, >, >=
5 ==, !=
6 not, or, and
7 =, %=, /=, -=, +=, *=, **=

1-2a_tipos_datos.py


Modulo Math

import math

Constantes:

pi, e, tau, inf, nan ( math.pi ; math.cos(0) )

Funciones math

Función Detalle Ejemplo
ceil Redondea al sgte. entero ceil(3.2) # 4
floor Redondea al entero anterior floor(3.2) # 3
ceil Valor absoluto fabs(-4) # 4
factiorial Func. factorial factorial(4) # 24

Funciones de potencia y logarítmicas

Función Detalle Ejemplo
exp e^x exp(1) # e
expm1 (e^x) -1 exp(1)e -1 # e-1
log logaritmo natural log(e) # 1
log2 logaritmo en base 2 log(2) # 1
log10 logaritmo en base 10 log(10) # 1
pow Potencia pow(3,2) # 9
sqrt Raíz cuadrada sqrt(9) # 3

Funciones trigonométricas

Función Detalle Ejemplo
acos arco coseno acos(1) # 0
asin arco seno asin(0) # 0
atan arco tangente atan(0) # 0
cos coseno cos(pi) # -1
hypot hipotenusa hypot(1,1) # 1.14121356...
sin seno sin(pi/2) # 1
tan tangente tan(pi/4) # 0.99999999...

Consola de python: python -i

>>> import math
>>> help(math)
>>> math.sqrt(16)
4.0
>>> math.log(math.e)
1.0

Modulo Random

Forma parte de la libreria estandar de python
Consola de python: python -i

>>> import random

>>> random.random()
0.1430076482629129

>>> random.random()*10
6.753608889973483

>>> (random.random()*10)%6+1
2.279082688613001

>>> (int(random.random()*10)%6+1)
4

>>> (int(random.random()*10)%6+1)
4

>>> (int(random.random()*10)%6+1)
6

>>> (int(random.random()*10)%6+1)
4

>>> (int(random.random()*10)%6+1)
3

>>> clear

Choice

Consola de python: python -i

>>> random.choice([1,2,3,4,5,6])
1

>>> random.choice([1,2,3,4,5,6])
1

>>> random.choice([1,2,3,4,5,6])
2

>>> random.choice([1,2,3,4,5,6])
4

>>> random.choice(['Rojo', 'Verde', 'Azul])
random.choice(['Rojo', 'Verde', 'Azul])

>>> random.choice(['Rojo', 'Verde', 'Azul'])
'Verde'

>>> random.choice(['Rojo', 'Verde', 'Azul'])
'Verde'

>>> random.choice(['Rojo', 'Verde', 'Azul'])
'Rojo'

>>> random.choice(['Rojo', 'Verde', 'Azul'])
'Verde'

Choices

Consola de python: python -i

>>> random.choices([1,2,3,4,5,6], k=2)
[4, 6]

>>> random.choices([1,2,3,4,5,6], k=2)
[4, 3]

>>> random.choices([1,2,3,4,5,6], k=2)
[3, 4]

1-2b_libreria_math.py


Condicionales

x = 2

if x >= 0:
    print('El número',x,'es positivo')
else:
    print('El número',x,'es negativo')

       # El número 2 es positivo

Condicionales Encadenados

if x >= 0:
    print('El número',x,'es positivo')
elif x < 0:
    print('El número',x,'es negativo')
else:
    print('El número es igual a cero')

       # El número 2 es positivo

Condicionales Anidados

x = 0
if x > 0:
    print('El número',x,'es positivo')
else:
    if x < 0:
        print('El número',x,'es negativo')
    else:
        print('El número es igual a cero')

       # El número es igual a cero

Mas ejemplos

x = 1
if x > 0:
    print('El número es positivo')
#        El número es positivo
x = -1
if x > 0:
    print('El número es positivo')
x = 1
if x % 2 == 0:
    print('El número',x,'es par')
else:
    print('El número',x,'es impar')
#        El número 1 es impar
x = 4
if x % 2 == 0:
    print('El número',x,'es par')
else:
    print('El número',x,'es impar')
#        El número 4 es par
x = 3
print('El número',x,'es par') if x % 2 == 0 else print('El número',x,'es impar')
#        El número 3 es impar

Otros ejemplos de encadenado

x = 1
y = 2
if x < y:
    print(x,'es menor q', y)
elif x > y:
    print(x,'es mayor q', y)
else:
    print(x,'es igual a', y)
#   1 es menor q 2
x = 3
if x < y:
    print(x,'es menor q', y)
elif x > y:
    print(x,'es mayor q', y)
else:
    print(x,'es igual a', y)
#   3 es mayor q 2
x = 2
if x < y:
    print(x,'es menor q',y)
elif x > y:
    print(x,'es mayor q',y)
else:
    print(x,'es igual a', y)
#   2 es igual a 2
x = 5
if x == y:
    print(x,'es igual a',y)
else:
    if x < y:
        print(x,'es menor q',y)
    else:
        print(x,'es mayor q',y)
#   5 es mayor q 2

1-3a_condicionales.py


Funciones

  • FUNCION
    Es una secuencia de sentencias que realiza una operación.
    Las mismas tienen un nombre y pueden recibir o no parámetros y devolver o no resultados.

ej.

def cero():
    return 0

cero()      # 0
cero() + 1  # 1
c = cero()
c           # 0
def suma_uno(un_numero):
    return un_numero + 1

suma_uno(3)      
# 4

suma_uno(cero()) 
#1


def suma(a, b):
    resultado = a + b
    return resultado

def suma(a, b):
    resultado = a + b
    return resultado

def maximo_2(a, b):
    "Devuelve el máximo entre a y b"
    maximo = a
    if b > a:
        maximo = b
    return maximo
 
def maximo_3(a, b, c):
    "Devuelve el máximo enter a, b, y c"
    return maximo_2(a, maximo_2(b,c))


print(maximo_2(2,5))
# 5

print(maximo_3(6, 1, 5))
# 6

Parametros de función

def peso(masa, gravedad=9.8):
    "Fórmula del peso"
    return masa * gravedad

Parametros opcionales

print("Peso en la tierra:", peso(10)) 
# Peso en la tierra: 98.0

print("Peso en la luna:", peso(10, 1.63))
# Peso en la luna: 16.299999999999997

Parámetros con palabras claves (o argumentos nombrados)

print("Peso en la luna:", peso(10, gravedad=1.63))
# Peso en la luna: 16.299999999999997

print("Peso en la luna:", peso(masa=10, gravedad=1.63))
# Peso en la luna: 16.299999999999997

print("Peso en la luna:", peso(gravedad=1.63, masa=10))
# Peso en la luna: 16.299999999999997

Los parámetros posicionales no pueden ir despues de un keyword

print("Peso en la luna:", peso(masa=10, 1,63))
# SyntaxError: positional argument follows keyword argument

Lista de parámetros

def suma_numeros(*args):
    "Suma los números pasados por párametro"
    return sum(args)

print("6 + 7 + 8 =", suma_numeros(*[6,7,8]))
#        6 + 7 + 8 = 21

print("6 + 7 + 8 =", suma_numeros(6,7,8))
#        6 + 7 + 8 = 21

Diccionario de parámetros

def imprimir_ticket(*args, **kwargs):
    "Imprime el ticket de una compra"
    print("Detalle Ticket")
    for item, precio in kwargs.items():
        print(item, ":", precio)

Argumentos de función

  • Distintas formas de pasar los argumentos
  • Definir funciones anónimas o expresiones lambda

Definiendo Funcion Fibonacci (hasta limite determinado)

# *def para definir la funcion
def fibo(n):
    """Muestra la serie Fibonacci hasta n."""
    a, b = 0, 1
    while a < n:
        print(a, end=' ')
        a, b = b, a+b
    print()
 
fibo(2000)
# 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597
  • return: Devuelve un valor en una función, sin una expresión como argumento retorna None, si se alcanza el fuba de una función, también retorna None.
f = fibo

f(1000)
# 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987

print(f(0))
# None

type(f)
# <class 'function'>

Fibo 2

def fibo2(n):
    """Devuelve una lista con la serie de Fibonacci hasta n."""
    result = []
    a, b = 0, 1
    while a < n:
        result.append(a)
        a, b = b, a+b
    return result

f100 = fibo2(100)

f100
# [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]

Ejemplo de función que llama a otra

def fib(n):
    a, b = 0, 1
    for i in range(n):
        a, b = b, a+b
    return a

print(fib(35))

def fibo(n):
    a = fib(n-1) + fib(n-2)
    return a

print(fibo(35))

Función que recibe entrada de usuario

def pedir_confirmacion(prompt, reintentos=4, msj='Intenta nuevamente'):
    while True:
        ok = input(prompt)
        if ok in ('s', 'S', 'si', 'Si', 'SI'):
            return True
        if ok in ('n', 'no', 'No', 'NO'):
            return False
        reintentos -= 1
        if reintentos < 0:
            raise ValueError('Respuesta de usuario invalida')
        print(msj)
> pedir_confirmacion('¿Quieres Salir?')
> ¿Quieres Salir?no
> False

> pedir_confirmacion('Sobreescribir?', 2, 'eeey! si o no?')
> Sobreescribir?o
> eeey! si o no?
> Sobreescribir?no
> False

Levantando excepción ValueError

> pedir_confirmacion('¿Sobreescribir?', 2)
> ¿Sobreescribir?e
> Intenta nuevamente
> ¿Sobreescribir?3
> Intenta nuevamente
> ¿Sobreescribir?3
> Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
   File "<stdin>", line 10, in pedir_confirmacion
  ValueError: Respuesta de usuario invalida

Los valores por omisión son evaluados en el momento de la definición de la función, en el ámbito de la definición, entonces:

i = 5

def f(arg=i):
    print(arg)

i = 6

f()
# 5

f(6)
# 6

f()
#5

El valor por omisión es evaluado solo una vez. Existe una diferencia cuando el valor por omisión es un objeto mutable como una lista, diccionario, o instancia de la mayoría de las clases. Por ejemplo.

La siguiente función acumula los argumentos que se le pasan en subsiguientes llamadas:

def f(a, L=[]):
    L.append(a)
    return L

print(f(1)) #[1]
print(f(2)) #[1, 2]
print(f(3)) #[1, 2, 3]

Si no se quiere que el valor por omisión sea compartido entre subsiguientes llamadas, la función se puede escribir así:

def f(a, L=None):
    if L is None:
            L = []
    L.append(a)
    return L

print(f(1))
# [1]

print(f(2))
# [2]

print(f(3))
# [3]

print(f(1, [1,2,3]))
# [1, 2, 3, 1]

(o argumentos nombrados) de la forma keyword = value. Por ejemplo:

def loro(tension, estado='muerto', accion='explotar', color='Azul Nordico'):
    print("-- Este loro no va a", accion, end=' ')
    print("si le aplicas", tension, "voltios.")
    print("-- Hermoso plumaje", color)
    print("-- Está", estado,"!")
  • 1 argumento posicional

    loro(1000)
    # -- Este loro no va a explotar si le aplicas 1000 voltios.
    # -- Hermoso plumaje Azul Nordico
    # -- Está muerto !
    
  • 1 argumento nombrado

    loro(tension=1000)
    # -- Este loro no va a explotar si le aplicas 1000 voltios.
    # -- Hermoso plumaje Azul Nordico
    # -- Está muerto !
    
  • 2 argumentos nombrados

    loro(tension=1000000, accion='volar')
    # -- Este loro no va a volar si le aplicas 1000000 voltios.
    # -- Hermoso plumaje Azul Nordico
    # -- Está muerto !
    
  • 2 argumentos nombrados

    loro(accion='volar', tension=1000000)
    # -- Este loro no va a volar si le aplicas 1000000 voltios.
    # -- Hermoso plumaje Azul Nordico
    # -- Está muerto !
    
  • 3 args posicionales

    loro('un millón', 'despojado de vida', 'saltar')
    # -- Este loro no va a saltar si le aplicas un millón voltios.
    # -- Hermoso plumaje Azul Nordico
    # -- Está despojado de vida !
    
  • 1 arg. posicional y 1 nombrado.

    loro('mil', estado='viendo crecer las flores desde abajo')
    # -- Este loro no va a explotar si le aplicas mil voltios.
    # -- Hermoso plumaje Azul Nordico
    # -- Está viendo crecer las flores desde abajo !
    

Llamadas invalidas

loro()
# falta argumento obligatorio

loro(tension=5.0, 'muerto')
# argumento posicional luego de uno nombrado

loro(110, tension=220)
# valor duplicado para el mismo argumento

loro(actor='Juan Garau')
# nombre del argumento desconocido

Cuando un parámetro formal de la forma nombre está presente al final, recibe un diccionario (ver tipos integrados) conteniendo todos los argumentos nombrados excepto aquellos correspondientes a un parámetro formal.

Esto puede ser combinado con un parámetro formal de la forma nombre, que recibe una tupla conteniendo los argumentos posicionales además de la lista de parámetros formales. *nombre debe ocurrir antes de **nombre.

Ejemplo:

def ventadequeso(tipo, *argumentos, **palabrasclave):
    print("-- ¿Tiene", tipo,"?")
    print("-- Lo siento, nos quedamos sin", tipo)
    for arg in argumentos:
        print(arg)
    print("-" * 40)
    for c in palabrasclave:
        print(c, ":", palabrasclave[c])
ventadequeso("Limburger", "Es muy liquido, sr.",
             "Realmente es muy muy liquido, sr.",
             cliente="Juan Garau",
             vendedor="Miguel Paez",
             puesto="Venta de Queso")

#- ¿Tiene Limburger ?
#- Lo siento, nos quedamos sin Limburger
# Es muy liquido, sr.
# Realmente es muy muy liquido, sr.
# ----------------------------------------
#           cliente : Juan Garau
#           vendedor : Miguel Paez
#           puesto : Venta de Queso Argentino

Listas de argumentos arbitrarios

Una función puede ser llamada con un número arbitrario de argumentos.
Estos serán organizados en una tupla.
Antes del número variable de argumentos, cero o más argumentos normales pueden estar presentes.

def muchos_items(archivo, separador, *args):
    archivo.write(separador.join(args))

Generalmente, argumentos de cantidad variable son útilmos en la lista de parametros formales, porque toman el remanente de argumentos q se pasan a la función.

Cualquier parametro que suceda luego del +args solo sera del tipo nombrado, es decir, solo se pueden utilizar nombradros y no posicionales.

concatenar("tierra", "marte", "venus")
#   'tierra/marte/venus'

concatenar("tierra", "marte", "venus", sep=" @ ")
#   'tierra @ marte @ venus'

Desempaquetando una lista de argumentos

Cuando los argumentos ya pertences a una lista o tupla, se pueden desempaquetar para llamar una funcion que requiere argumetnoss posicionaes separados.

ej. range() espera los argumentos inicio y fin.

También se puede llamar a la función con el operador para desempaquetar argumentos de una lista o tulpa *

# llamada normal con argumentos separados
list(range(3, 6))
# [3, 4, 5]

# argumentos desempaquetados de la lista
args = [3, 6]
list (range(*args))
# [3, 4, 5]

Los diccionarios pueden entregar argumentos nombrados con el operador **

def loro(tension, estado='rostizado', accion='apestar'):
    print("-- Este loro no va a", accion, end=' ')
    print("si toca", tension, "voltios.", end=' ')
    print("Está", estado, "!")

d = {"tension": "cinco mil", "estado": "demacrado", "accion": "VOLAR"}

loro(**d)
# -- Este loro no va a VOLAR si toca cinco mil voltios. Está demacrado !

1-3b_funciones.py


Expresiones Lambda

Funciones anónimas, pequeñas son creadas con lambda.

# retorna la suma de sus dos argumentos
lambda a, b: a + b

Las funciones Lambda pueden ser usadas en cualquier lugar donde sea requerido un objeto de tipo función.

Están sintácticamente restringidas a una sola expresión.

Semánticamente, son solo azúcar sintáctica para definiciones normales de funciones.

Al igual que las funciones anidadas, las funciones lambda pueden hacer referencia a variables desde el ámbito que la contiene.

def hacer_incrementador(n):
    return lambda x: x + n

f = hacer_incrementador(42)
f(0)
# 42

f(1)
# 43

f(10)
# 52
import time

f = lambda x: x + 1

print("Tipo de f:", type(f))
# Tipo de f: <class 'function'>

print("f(3)=", f(3))
# f(3)= 4

def funcioN_time(f, *args):
    start_time = time.time()
    result = f(*args)
    end_time = time.time()
    print("Tiempo de ejecución: ", end_time - start_time, "milisegundo(s)")
    return result

print("f(5) =", funcioN_time(f, 5))
# Tiempo de ejecución:  2.86102294921875e-06 milisegundo(s)

f(5) = 6

1-3c_expresiones_lambda.py


Docstrings

Ejemplo de un docstring multi-línea

def mi_funcion():
    """Esta funcion solo muestra documentacion.
     
    Nada mas.
    """
    pass
 
print(mi_funcion.__doc__) 
# Esta funcion solo muestra documentacion.
#
# Nada mas.

Anotación de funciones

Se almacenan en el atributo annotations de la función como un diccionario y no tienen efecto enninguna otra parte de la función.

Las anotaciones de los parámetros se definen luego de dos puntos después del nombre del parámetro, seguido de una expresión que evalúa al valor de la anotación.

Las anotaciones de retorno son definidas por el literal ->, seguidas de una expresión, entre la lista de parámetros y los : que marcan el final de la declaración def.

El siguiente ejemplo tiene un argumento posicional, uno nombrado, y el valor de retorno anotado.

def f(jamon: str, huevos: str = 'huevos') -> str:
    print("Anotaciones:", f.__annotations__)
    print("Argumentos:", jamon, huevos)
    return jamon + ' y ' + huevos

f('carne')
# Anotaciones: {'jamon': <class 'str'>, 'huevos': <class 'str'>, 'return': <class 'str'>}
# Argumentos: carne huevos
# 'carne y huevos'

1-3d_cadena_de_txt_de_documentacion.py


Ejemplos print, if, for ,range, while

print

print("El número es: ", 5)
# El número es:  5
print(1,2,3,4,5, sep=', ')
# 1, 2, 3, 4, 5
print(1,2,3,4,5, sep='-')
# 1-2-3-4-5
# Cambio salto de lina por end=''
print(1,2,3,4,5, sep=' - ', end='')
# 1 - 2 - 3 - 4 - 5
print([1,2,3,4,5])
# [1, 2, 3, 4, 5]

if

Consola python: python -i

x = int(input("Ingresa un entero: "))

# Ingresa un entero: 42

x = 42

if x < 0:
    x = 0
    print('Negativo cambiado a cero')
elif x == 0:
    print('Cero')
elif x == 1:
    print('Simple')
else:
    print('Más')
  
'Más'

for

Midiendo cadenas de texto

palabras = ['gato','ventana','defenestrado']

for p in palabras:
    print(p, len(p))

# gato 4
# ventana 7
# defenestrado 12


for p in palabras[:]:
    if len(p) > 6:
        palabras.insert(0, p)
    
palabras
# ['defenestrado', 'ventana', 'gato', 'ventana', 'defenestrado']         
for i in range(10):
    print(i, end=' ')

print('\n')

for i in 'Hola Mundo!':
    print(i, end=' - ')

print('\n')

def contador(n):
    c = 0
    for i in range(n):
        c += 1
    return c

contador(10)
print(contador(10),'\n')

def sumatoria(numeros):
    acum = 0
    for n in numeros:
        acum += n
    return acum

print(sumatoria([1,2,3,4,5]), '\n')


def tabla_multip(numero):
    "Imprime la tabla de multiplicar"
    for indice in [1, 2, 3, 4, 5, 6, 7, 8, 9 ,10]:
        print(f"{numero} * {indice} = {numero * indice}")

tabla_multip(2)

range

range( desde<0>, hasta<definir>, paso<1> ) 
       <Valores por defecto>
for x in range(10):
    print(x, end=' ')

# 0 1 2 3 4 5 6 7 8 9
for x in range(1,10):
    print(x, end=' ')

# 1 2 3 4 5 6 7 8 9
for x in range(1,10,2):
    print(x, end=' ')

# 1 3 5 7 9
for x in range(10,0,-1):
    print(x, end=' ')

# 10 9 8 7 6 5 4 3 2 1
for x in range(2):
    print(i)

# 0
# 1
# 2
range(5, 10)
# 5, 6, 7, 8, 9
range(0, 10, 3)
# 0, 3, 6, 9
range(-10, -100, -30)
# -10, -40, -70
a = ['Mary','tenía','un','corderito']

for i in range(len(a)):
    print(i, a[i])

# 0 Mary
# 1 tenía
# 2 un
# 3 corderito

Crear lista a partir de objeto iterable

# list(enumerate())  

list(range(5))
# [0, 1, 2, 3, 4]

Ciclo while

import time

def suma_n(n):
    "Suma los números de 1 a n"
    result = 0
    x = n
    while x > 0:
        result += x
        x -= 1
    return result

print(suma_n(5))
def ciclo_infinito():
    "Imprime el número 1 unfinitas veces"
    i = 1
    while i <= 10:
        print(i, end=" ")
        time.sleep(.5)

#ciclo_infinito()

1-4a_if_for_range_while.py


Sentencias brake, else y continue

for n in range(2, 10):
    for x in range(2, n):
        if n % x == 0:
            print(n,'es igual a',x,'*',n/x)
            break
    else:
        # "else" de un ciclo "for"
        # Si no encuentra un factor
        print(n, 'es un número primo')

# 2 es un número primo
# 3 es un número primo
# 4 es igual a 2 * 2.0
# 5 es un número primo
# 6 es igual a 2 * 3.0
# 7 es un número primo
# 8 es igual a 2 * 4.0
# 9 es igual a 3 * 3.0
for num in range(2, 10):
    if num % 2 == 0:
        print("Encontré un número par", num)
        # "continue" continua con la sgte. iteracion del ciclo for
        continue
    print("Encontré un número", num)

# Encontré un número par 2
# Encontré un número 3
# Encontré un número par 4
# Encontré un número 5
# Encontré un número par 6
# Encontré un número 7
# Encontré un número par 8
# Encontré un número 9

else, break

def buscar_numero_en(numero, lista):

    for i, item in enumerate(lista):
        if item == numero:
            indice = i
            break
    else:
        indice = -1
    return indice

print( buscar_numero_en(1, [2,3,1,4,5]))
# 2

print( buscar_numero_en(1, [2,6,3,4,5]))
# -1

La sentencia pass no hace nada, se puede usar cuando una sentencia es requerida
por la sintáxis, pero no se requiere ningúna acción, ej.

# Espera hasta una interrupción de teclado [Ctrl]+[C]
while True:
    pass

Es usada normalmente para crear clases en su mínima expresión

    class MyClaseVacia:
        pass

Otro lugar donde se puede usar "pass" es como marca de para una función o un cuerpo condicional (ej. en código nuevo), te permite pensar a un nivel de abstracción mayor.

El pass se ignora silenciosamente:

    class initlog(*args):
        pass # Recordar implementar esto!!!
def a_function(x):
    result = 0
    if x > 0 and x < 5:
        result = x ** 2
    elif x >= 5 and x < 10:
        pass
    else:
        result = (x ** 4) + 1

    return result

print(a_function(2))
print(a_function(7))
print(a_function(12))

1-4b_brake-else-continue.py


Entorno Virtual

ej. tutorial-env

Crear Entorno Virtual

python3 -m venv tutorial-env

Activar Entorno Virtual

source tutorial-env/bin/activate

Acceder a la consola de Python en el entorno virtual

(tutorial-env) python
Python 3.8.2 (default, Apr 27 2020, 15:53:34) 
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
 import sys
 sys.path
['', 
     '/usr/lib/python38.zip', '/usr/lib/python3.8', 
     '/usr/lib/python3.8/lib-dynload',
     '/Coursera1/modulo4/tutorial-env/lib/python3.8/site-packages'
     ]

1-4c_entorno_virtual.py


import

import sentencia_break

sentencia_break.buscar_numero_en(1, [3,2,1,0])
# 2
from sentencia_break import buscar_numero_en

buscar_numero_en(1, [3,5,2,1,6])
# 3
from sentencia_break import buscar_numero_en as bn

bn(1, [5,7,9,3,9,1,0])
# 5 

Crear archivo __init__.py en carpeta modulo4, acceder a la consola
de python un nivel mas arriba en el árbol de directorios.

import modulo4
from modulo4 import sentencia_break
from modulo4.sentencia_break import buscar_numero_en as bn

bn(4,[0,1,2,3,4,5,6])
# 4

Python tiene una manera de poner definiciones en un archivo y usarlos en un script o en una instancia interactiva del intérprete.

Tal archivo es llamado módulo, las definiciones de un módulo pueden ser importadas a otros módulos o al módulo principal.

Un módulo contiene definiciones y declaraciones de Python, el nombre del archivo es modulo.py

__name__ : variable global que contiene el nombre del modulo.

Usando módulo de ejemplo creado como fibo.py

Consola python: python -i

>>> import fibo
>>> 
>>> fibo.fib(1000)
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 
>>> fibo.fib(100)
1 1 2 3 5 8 13 21 34 55 89 
>>> fibo.__name__
'fibo'
>>> # Se puede usar un variable local asignandole la funcion
>>> fib = fibo.fib
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377 

Cada módulo tiene su propio espacio de nombres usado de forma global por todas
las funciones definidas en el módulo.

Se pueden modificar las variables globales de un módulo nombre_modulo.nombre_item.

Los módulos pueden importar otros módulos.

Una variante de la declaración import que importa los nombres de un módulo
directamente al espacio de nombres del módulo que hace la importación.

>>> from fibo import fib, fib2
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377

Variante para importar todos los nombres que un módulo define:

>>> from fibo import *
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377

La práctica de importar * de un módulo o paquete es mal vista. Ya que, frecuentemente
genera un código poco legible. Sin embargo, está bien usarlo en sesiones interactivas.

Recargar modulo:

import importlib
importlib.reload(modulename)

Ejecutando módulos como scripts

python fibo.py <argumentos>

El codigo en el módulo es ejecutado como si fuese importado producto de : __name__ = "__main__".

Si agregamos al final del modulo fibo.py

if __name__ == "__main__":
    import sys
    fib(int(sys.argv[1]))

en terminal:

$ python fibo.py 50
1 1 2 3 5 8 13 21 34

Si el módulo se importa ese código no se ejecuta:

>>> import fibo
>>>

Importar módulos individuales

import sound.effects.echo

# uso
sound.effects.echo.echofilter(input, output, delay=0.7, atten=4){1}        

Otra alternativa para importar el submódulos es:

from sound.effects import echo

# uso
echo.echofilter(input, output, delay=0.7, atten=4

1-4d_import_modulos_paquetes.py


Modulo fibo

Modulo para obtener los números de fibonacci ./fibo.py

def fib(n): # escribe la serie Fibonacci hasta n
    a, b = 0, 1
    while b < n:
        print(b, end=' ')
        a, b = b, a+b
    print()

def fib2(n): # devuelve la serie Fibonacci hasta n
    resultado = []
    a, b = 0, 1
    while b < n:
        resultado.append(b)
        a, b = b, a+b
    return resultado

if __name__ == "__main__":
    import sys
    fib(int(sys.argv[1]))

fibo.py


Iteradores

Tipos de datos que pueden ser recorridos secuencialmente mediante el uso del ciclo for.

Los objetos iterables dében responder los mensajes: __iter__ y __next__

  • __iter__ : retorna un objeto iterador.
  • __next__ : retorna el próximo elemento de la secuencia.

ej:

lista = [1, 2, 3, 4, 5]

for elemento in lista:
    print('\t ',elemento, end=' ')

#	  1 	  2 	  3 	  4 	  5

for llama a la función iter() de la lista (objeto iterable) y recibe un elemento definido por __next__.

Cuando no hay mas elementos next levanta una excepción del tipo Stoplteration que notifica al ciclo for que debe finalizar.

Conociendo el uso interno del ciclo for podemos crear iteradores propios.

__next__ : debe contiener la lógica de como acceder al siguiente elemento de la secuencia.

__iter__ y __next__ : y todos aquellos metodos que comienzan y terminan con doble guión bajo, su proposito es ser invocado por Python internamente, en este ejemplo por el ciclo for.

Ejemplo de un iterador que recorre elementos de una lista en sentido inverso.

class Reversa:
    """
    Iterador inverso.
    """ 
    def __init__(self, datos):
        self.datos = datos
        self. indice = len(datos)
        
    def __iter__(self):
        return self
        
    def __next__(self):
        if self.indice == 0:
            raise StopIteration()
        self.indice -= 1
        return self.datos[self.indice]

 
    for elemento in Reversa([1, 2, 3, 4]):
        print(elemento, end=' ')

python -v

>>> lista = [1, 2, 3]
>>> it = iter(lista)
>>> it
<list_iterator object at 0x7fce335ce610>
>>> next(it)
1
>>> next(it)
2
>>> next(it)
3
>>>next(it)
Traceback (most recent call last):
  File "/usr/lib/python3.8/code.py", line 90, in runcode
    exec(code, self.locals)
  File "<input>", line 1, in <module>
StopIteration
class Iterator:
    """
    Iterador, retorna elementos de
    posiciones pares de una lista
    """

    def __init__(self, data):
        self.data = data
        self.indice = 0

    def __iter__(self):
        return self

    def __next__(self):
        if self.indice >= len(self.data):
            raise StopIteration()
        elem = self.data[self.indice]
        self.indice += 2
        return elem

it = Iterator([1, 2, 3, 4, 5, 6])

for e in it:
    print('\t', e)

#   1
#   3
#   5

1-4e_iteradores.py


Debugger

import pdb

Breakpoint en la linea donde se requiera:

pdb.set_trace()

Comandos para tomar control de la ejecución

Comando Detalle
h(elp) Muestra la ayuda de todos los comandos que provee pdb.
s(tep) Ejecuta la línea actual, si hay una llamada de función se mete dentro del código
de la función para poder seguir la ejecución de la misma.
n(ext) Continúa la ejecución hastala próxima línea.
r(eturn) Continúa la ejecución hasta el return de la función actual.
c(ontinue) Continúa la ejecución hasta el próximo breakpoint o hasta el fin del programa.
l(ist) Muestra el código del archivo actual.
p Evalúa la expresión pasada como parámetro, en el contexto actual e imprime su valor.
q(uit) Sale del depurador. El programa es abortado.

Ayuda del debugger

> (Pdb) h

    Documented commands (type help <topic>):
    ========================================
    EOF    c          d        h         list      q        rv       undisplay
    a      cl         debug    help      ll        quit     s        unt      
    alias  clear      disable  ignore    longlist  r        source   until    
    args   commands   display  interact  n         restart  step     up       
    b      condition  down     j         next      return   tbreak   w        
    break  cont       enable   jump      p         retval   u        whatis   
    bt     continue   exit     l         pp        run      unalias  where    
    
    Miscellaneous help topics:
    ==========================
    exec  pdb

ej. breakpoint pdb.set_trace()

pdb.set_trace()   # <-- Breakpoint
def a_function(a_number):
    """
        La función recibe un número @a_number y:
        Si es par:
            Si es múltiplo de 10:
                devuelve el número dividido en 2
            Si es múltiplo de 8:
                devuelve el número dividido en 4
            si es otro resta 1
        Si es impar:
            Si es múltiplo de 3:
                devuelve el número multiplicado por 11
            Si es múltiplo de 7:
                devuelve el número multiplicado por 23
            si es otro suma 1
    """

    pdb.set_trace()   # <-- Breakpoint
    result = None
    if a_number %2 == 0:
        if a_number % 10 == 0:
            result = a_number / 2
        elif a_number % 8 == 0:
            result = a_number - 1
        else:
            result = a_number -1
    else:
        if a_number % 3 == 0:
            result = a_number * 11
        elif a_number % 7 == 0:
            result = a_number * 23
        else:
            result = a_number + 1
    return result

result_1 = a_function(20)
print(result_1)
print('END')

1-4f_debugger.py


Ejercicios

Actividad 1

En la consola interactiva de Python o en un script de Python,
escribir un programa para resolver el siguiente problema:

¿Cuál es el resultado de sumar los primeros 50 números pares?
(Desde el 2 inclusive hasta el 100 inclusive)

def eval():
    """
    Imprime la suma de los primeros 50 pares de 2 a 100
    """
    var = 0
    for i in range(2,101):
        if i % 2 == 0:
            var += i
    print(var)


eval()
# 2550

1-4g_actividad_evaluada.py


Actividad Dados

Requerimientos

Crear un programa que simule la tirada de dados.

Cada vez que ejecutamos el programa, éste elegirá dos números aleatorios entre el 1 y el 6.

El programa deberá imprimirlos en pantalla, imprimir su suma y preguntarle al usuario si quiere tirar los dados otra vez.

from random import random   # importe de la función random() del modulo random

def tirar_dados():
    """Retorna una lista de 3 enteros [dado1, dado2, dado1 + dado2]"""
    # llamado a random.random() y se define un "rango"
    dado1 = int((random() * 10) % 6 + 1)                        
    dado2 = int((random() * 10) % 6 + 1)
    suma_dados = dado1 + dado2
    return [dado1, dado2, suma_dados]

# Variable usada para indicar el término de la ejecución
continuar = True

while continuar:
    # Asignación de la lista retornada por la función tirar_dados()
    dados = tirar_dados()
    # Formateo de texto según valores en la lista dados[]
    print('''
        Lanzando dados!

        dado 1 -> [{0}]
        dado 2 -> [{1}]
        ---------------
        TOTAL --> [{2}]
        '''.format(dados[0], dados[1], dados[2]))
    # Pregunta y asignación, simula un "si por defecto"
    respuesta = input('¿Tirar dados nuevamente? [SI/no]: ').upper()
    # Lista de posibles respuestas de usuario para finalizar el programa
    if respuesta in 'NO':
        # Indica el fin del ciclo while y finaliza el programa.
        continuar = False

quit()

1-5_evaluacion_dados.py