**Ir a:** [*Repositorio*](https://gitea.kickto.net/devfzn/Apuntes_Python), [*Modulo 2*](https://gitea.kickto.net/devfzn/Apuntes_Python/src/branch/master/01_curso/Modulo_2#modulo-2-python-basico) ## Modulo 1 - Python basico #### [Indice](#modulo-1-python-basico) - [Primeros Pasos](#primeros-pasos) - [Tipos de Datos](#tipos-de-datos) - [Modulo Math](#modulo-math) - [Condicionales](#condicionales) - [Funciones](#funciones) - [Expresiones Lambda](#expresiones-lambda) - [Docstrings](#docstrings) - [Ejemplos print, if, for, range y while](#ejemplos-print-if-for-range-while) - [Sentencias brake, else y continue](#sentencias-brake-else-y-continue) - [Entorno Virtual](#entorno-virtual) - [import](#import) - [modulo fibo](#modulo-fibo) - [Iteradores](#iteradores) - [Debugger](#debugger) - [Ejercicios](#ejercicios) - [Actividad 1](#actividad-1) - [Actividad Dados](#actividad-dados) ## Primeros Pasos Hola Mundo! ```python print("Hola Mundo") ``` Entrada de usuario ```python nombre = input("Ingresa tu nombre: ") print("Hola", nombre, "!") ``` Ejemplo fibo ```python # 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 # shift + Enter para terminar de ingresar el ciclo while # en consola, o agregar otra linea con Enter. ``` Print básico ```python 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** ` // ` ```python 4//3 # 1 ``` **Resto** ` % ` ```python 4%3 # 1 ``` **Potencia** ` ** ` ```python # 5 al cuadrado 5 ** 2 # 2 a la potencia de 7 2 ** 7 ``` **Última expresion** ` _ ` ```python 1+3 # 4 3 + _ # 7 ``` **Redondeo** `round("número", "decimales")` ```python 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'** ```python 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 **` \ `** ```python 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 ```python # 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) ``` ```python 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 x[0] x[0][1] ``` [1-1_primeros_pasos.py](https://gitea.kickto.net/devfzn/Apuntes_Python/src/branch/master/01_curso/Modulo_1/1-1_primeros_pasos.py) ---- # Tipos de Datos Consola python: `python -i` ```python >>> type(8) >>> type(10.5) >>> type(True) >>> type('hola') >>> type(3+4j) ``` ### Variables - Tipado dinámico - CaseSensitive ```python >>> numero = 4 >>> type(numero) >>> numero = 4.5 >>> type(numero) >>> nada = None >>> type(nada) ``` **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 |Op1|Op2|Resultado |-|-|-| | True | True | True | | True | False | False | | False | True | False | | False | False | False | #### or |Op1|Op2|Resultado |-|-|-| | True | True | True | | True | False | True | | False | True | True | | False | False | False | #### not |Op|Resultado |-|-| | True |False| | False|True | ### Precedencia de operadores | Orden Predecendencia|Operadores| |:-:|---------------| | 1 | `**` | | 2 | ` * `, ` / `, ` % `, ` // ` | | 3 | ` + `, ` - ` | | 4 | ` <= `, ` < `, ` > `, ` >= `| | 5 | ` == `, ` != ` | | 6 | ` not `, ` or `, `and ` | | 7 | ` = `, ` %= `, ` /= `, ` -= `, ` += `, ` *= `, ` **= ` | [1-2a_tipos_datos.py](https://gitea.kickto.net/devfzn/Apuntes_Python/src/branch/master/01_curso/Modulo_1/1-2a_tipos_datos.py) ---- ## Modulo Math ```python import math ``` Constantes: ```python 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` ```python >>> 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` ```python >>> 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` ```python >>> 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` ```python >>> 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](https://gitea.kickto.net/devfzn/Apuntes_Python/src/branch/master/01_curso/Modulo_1/1-2b_libreria_math.py) ---- ## Condicionales ```python 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 ```python 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 ```python 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 ```python x = 1 if x > 0: print('El número es positivo') # El número es positivo ``` ```python x = -1 if x > 0: print('El número es positivo') ``` ```python 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 ``` ```python 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 ``` ```python 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 ```python 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 ``` ```python 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 ``` ```python 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 ``` ```python 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](https://gitea.kickto.net/devfzn/Apuntes_Python/src/branch/master/01_curso/Modulo_1/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. ```python def cero(): return 0 cero() # 0 cero() + 1 # 1 c = cero() c # 0 ``` ```python 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 ```python def peso(masa, gravedad=9.8): "Fórmula del peso" return masa * gravedad ``` #### Parametros opcionales ```python 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) ```python 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** > ```python > print("Peso en la luna:", peso(masa=10, 1,63)) > # SyntaxError: positional argument follows keyword argument > ``` ### Lista de parámetros ```python 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 ```python 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) ```python # *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**. ```python 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) # ``` #### Fibo 2 ```python 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 ```python 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 rercibe entrada de usuario ```python 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) ``` ```python > 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** ```python > pedir_confirmacion('¿Sobreescribir?', 2) > ¿Sobreescribir?e > Intenta nuevamente > ¿Sobreescribir?3 > Intenta nuevamente > ¿Sobreescribir?3 > Traceback (most recent call last): File "", line 1, in File "", 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: ```python 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: ```python 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í: ```python 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] ``` #### Palabras clave como argumentos Las funciones también puede ser llamadas usando argumentos de palabras clave (o **argumentos nombrados**) de la forma `keyword = value`. Por ejemplo: ```python def loro(tension, estado='muerto', accion='explotar', tipo='Azul Nordico'): print("-- Este loro no va a", accion, end=' ') print("si le aplicas", tension, "voltios.") print("-- Gran plumaje tiene el", tipo) print("-- Está", estado,"!") ``` - 1 argumento posicional ```python loro(1000) # -- Este loro no va a explotar si le aplicas 1000 voltios. # -- Gran plumaje tiene el Azul Nordico # -- Está muerto ! ``` - 1 argumento nombrado ```python loro(tension=1000) # -- Este loro no va a explotar si le aplicas 1000 voltios. # -- Gran plumaje tiene el Azul Nordico # -- Está muerto ! ``` - 2 argumentos nombrados ```python loro(tension=1000000, accion='VOOOOM') # -- Este loro no va a VOOOOM si le aplicas 1000000 voltios. # -- Gran plumaje tiene el Azul Nordico # -- Está muerto ! ``` - 2 argumentos nombrados ```python loro(accion='VOOOOM', tension=1000000) # -- Este loro no va a VOOOOM si le aplicas 1000000 voltios. # -- Gran plumaje tiene el Azul Nordico # -- Está muerto ! ``` - 3 args posicionales ```python loro('un millón', 'despojado de vida', 'saltar') # -- Este loro no va a saltar si le aplicas un millón voltios. # -- Gran plumaje tiene el Azul Nordico # -- Está despojado de vida ! ``` - 1 arg. posicional y 1 nombrado. ```python loro('mil', estado='viendo crecer las flores desde abajo') # -- Este loro no va a explotar si le aplicas mil voltios. # -- Gran plumaje tiene el Azul Nordico # -- Está viendo crecer las flores desde abajo ! ``` #### Llamadas invalidas ```python 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: ```python 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]) ``` ```python 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. ```python 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. ```python 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 **`*`** ```python # 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 ` ** ` ```python 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](https://gitea.kickto.net/devfzn/Apuntes_Python/src/branch/master/01_curso/Modulo_1/1-3b_funciones.py) ---- ## Expresiones Lambda Funciones anónimas, pequeñas son creadas con **lambda**. ```python # 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. ```python def hacer_incrementador(n): return lambda x: x + n f = hacer_incrementador(42) f(0) # 42 f(1) # 43 f(10) # 52 ``` ```python import time f = lambda x: x + 1 print("Tipo de f:", type(f)) # Tipo de f: 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](https://gitea.kickto.net/devfzn/Apuntes_Python/src/branch/master/01_curso/Modulo_1/1-3c_expresiones_lambda.py) ---- ## Docstrings ### Ejemplo de un **docstring multi-línea** ```python 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 delpará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**. ```python def f(jamon: str, huevos: str = 'huevos') -> str: print("Anotaciones:", f.__annotations__) print("Argumentos:", jamon, huevos) return jamon + ' y ' + huevos f('carne') # Anotaciones: {'jamon': , 'huevos': , 'return': } # Argumentos: carne huevos # 'carne y huevos' ``` [1-3d_cadena_de_txt_de_documentacion.py](https://gitea.kickto.net/devfzn/Apuntes_Python/src/branch/master/01_curso/Modulo_1/1-3d_cadena_de_txt_de_documentacion.py) ---- ## Ejemplos print, if, for ,range, while ### print ```python print("El número es: ", 5) # El número es: 5 ``` ```python print(1,2,3,4,5, sep=', ') # 1, 2, 3, 4, 5 ``` ```python print(1,2,3,4,5, sep='-') # 1-2-3-4-5 ``` ```python # Cambio salto de lina por end='' print(1,2,3,4,5, sep=' - ', end='') # 1 - 2 - 3 - 4 - 5 ``` ```python print([1,2,3,4,5]) # [1, 2, 3, 4, 5] ``` ### if Consola python: `python -i` ```python 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 ```python 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'] ``` ```python 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 ```python range( desde<0>, hasta, paso<1> ) ``` ```python for x in range(10): print(x, end=' ') # 0 1 2 3 4 5 6 7 8 9 ``` ```python for x in range(1,10): print(x, end=' ') # 1 2 3 4 5 6 7 8 9 ``` ```python for x in range(1,10,2): print(x, end=' ') # 1 3 5 7 9 ``` ```python for x in range(10,0,-1): print(x, end=' ') # 10 9 8 7 6 5 4 3 2 1 ``` ```python for x in range(2): print(i) # 0 # 1 # 2 ``` ```python range(5, 10) # 5, 6, 7, 8, 9 ``` ```python range(0, 10, 3) # 0, 3, 6, 9 ``` ```python range(-10, -100, -30) # -10, -40, -70 ``` ```python 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 ```python # list(enumerate()) list(range(5)) # [0, 1, 2, 3, 4] ``` ### Ciclo while ```python 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)) ``` ```python 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](https://gitea.kickto.net/devfzn/Apuntes_Python/src/branch/master/01_curso/Modulo_1/1-4a_if_for_range_while.py) ---- ## Sentencias brake, else y continue ```python 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 ``` ```python 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 ```python 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. ```python # Espera hasta una interrupción de teclado [Ctrl]+[C] while True: pass ``` Es usada normalmente para crear **clases** en su mínima expresión ```python 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: ```python class initlog(*args): pass # Recordar implementar esto!!! ``` ```python 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](https://gitea.kickto.net/devfzn/Apuntes_Python/src/branch/master/01_curso/Modulo_1/1-4b_brake-else-continue.py) ---- ## Entorno Virtual ej. **tutorial-env** #### Crear Entorno Virtual ```bash python3 -m venv tutorial-env ``` #### Activar Entorno Virtual ```bash source tutorial-env/bin/activate ``` #### Acceder a la consola de Python en el entorno virtual ```bash (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](https://gitea.kickto.net/devfzn/Apuntes_Python/src/branch/master/01_curso/Modulo_1/1-4c_entorno_virtual.py) ---- ### import ```python import sentencia_break sentencia_break.buscar_numero_en(1, [3,2,1,0]) # 2 ``` ```python from sentencia_break import buscar_numero_en buscar_numero_en(1, [3,5,2,1,6]) # 3 ``` ```python 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. ```python 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](#modulo-fibo)*** Consola python: `python -i` ```python >>> 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. ```python >>> 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: ```python >>> 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: ```python import importlib importlib.reload(modulename) ``` #### Ejecutando módulos como scripts ```bash python fibo.py ``` El codigo en el módulo es ejecutado como si fuese importado producto de : **`__name__ = "__main__"`**. Si agregamos al final del modulo [fibo.py](#modulo-fibo) ```python if __name__ == "__main__": import sys fib(int(sys.argv[1])) ``` en terminal: ```bash $ 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 ```python 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: ```python from sound.effects import echo # uso echo.echofilter(input, output, delay=0.7, atten=4 ``` [1-4d_import_modulos_paquetes.py](https://gitea.kickto.net/devfzn/Apuntes_Python/src/branch/master/01_curso/Modulo_1/1-4d_import_modulos_paquetes.py) ---- ## Modulo fibo Modulo para obtener los números de fibonacci ***./fibo.py*** ```python 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](https://gitea.kickto.net/devfzn/Apuntes_Python/src/branch/master/01_curso/Modulo_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: ```python 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 ```python 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` ```python >>> lista = [1, 2, 3] >>> it = iter(lista) >>> it >>> 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 "", line 1, in StopIteration ``` ```python 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](https://gitea.kickto.net/devfzn/Apuntes_Python/src/branch/master/01_curso/Modulo_1/1-4e_iteradores.py) ---- ## Debugger ```python import pdb ``` #### Breakpoint en la linea donde se requiera: ```python 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 ): ======================================== 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()`** ```python 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](https://gitea.kickto.net/devfzn/Apuntes_Python/src/branch/master/01_curso/Modulo_1/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) ```python 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](https://gitea.kickto.net/devfzn/Apuntes_Python/src/branch/master/01_curso/Modulo_1/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. ```python 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](https://gitea.kickto.net/devfzn/Apuntes_Python/src/branch/master/01_curso/Modulo_1/1-5_evaluacion_dados.py)