Intro A La Computación Python
Intro A La Computación Python
TEORÍA
Introducción a la computación
Modelos abstractos
Enfoque algorítmico
Pensamiento lógico
Diagramas de flujo: conjunto de símbolos: inicio, fin, opera sobre entradas, tiene resultado,
distintos bloques representan operaciones y flechas de dirección
Unidad de control
Unidad aritmético lógica (recibe la entrada de dispositivos y hace cálculos: tiene contacto
con la memoria y emite la salida a través de dispositivos)
Capas de abstracción
(SOFT) Código de máquina, lenguaje ensamblador, lenguaje de alto nivel, algoritmo, problema
Lenguajes de programación
Son formales
Son explícitos
Libres de ambigüedades
Sintaxis
Errores de sintaxis (escritura formal), errores de semántica estática (“sumar números y palabras”)
y errores de semántica (“bug, ejecuta, pero sin sentido”), palabras reservadas del lenguaje
Python
Funciones built-in (integradas): abs(), help(), print(), input(), type(), str(), int(), float(), bool(), len(),
range(), round()
Secuencias de escape: ‘\n’ (salto), ‘\r’ (retrocede al comienzo de linea), ‘\b’ (retrocede un carácter
borrando el ultimo),’\t’ (agrega tabulación horizontal)
Consola
Interfaz para interactuar con el pc que ejecuta ordenes interpretadas por un Shell (interprete o
programa que interpreta las ordenes y comandos) de texto. Los más famosos: cmd, bash, zsh
Decisiones
Condicionales (if): estructura de control que cambia el flujo tomando decisiones, condición True o
False y una o mas sentencias en el cuerpo del if en caso de ser True (indentación necesaria)
Conversiones de tipos: implícita al comparar int con float o al ingresar “hola” el bool(“hola”) por
ejemplo o explicita utilizando la función de cada tipo por ejemplo bool(2132) es decir, castear
Number = 2
Símbolos:
09/03/23
Lógica binaria
Errores
Sdfsdfsd
Fasdssdfaafds
Except:
Asdjaghf
*Agregar while True para que repita hasta conseguir el resultado buscado
15/03/23
Ciclo: Estructura básica, repetir sentencias, estructura de repetición, existen ciclos con cantidad de
repeticiones desconocidas o indefinidas, existen ciclos con una cantidad de repeticiones fija,
definidas (desde que escribimos el código)
16/03/2023
Repite una cantidad de veces fija, depende de una secuencia de valores especificada, en cada
ciclo, se lee un valor de esa secuencia
Funcion range(): Comienza en start, para ANTES de stop, avanza de a step “for i in range(0 p
inicio ,4 o fin,1 o paso)”. Range(0,10,1) = Range(10). Devuelve un range, similar a “array”
23/03/23
Funciones
“””
Docstring (documentación)
“””
<sentencia>
Return <out>
Separar problemas
Autocontenidos
Reutilizables
Parametrizables
Código ordenado y coherente
Alcance (scoping)
¿Se puede utilizar variables definidas fuera de la función dentro? Sí (con su valor en el momento
de invocar la función, aunque prioriza el valor local) (si ya está definido, sino: UnboundLocalError)
(variables globales)
pero no utilizar variables definidas o alteradas dentro de la función fuera. (estas variables sólo
existen dentro de la función: variables locales)
Importar y alterar variables globales dentro de una función a partir de: global <nombre>
Buenas prácticas: mantener variables globales por un lado y locales por otro
29/03/23
Funciones
Def <name>(<arg1>=<value1>,…):
Pero se agregan sugerencias en args, no se modifica, solo sirve para documentar e interpretar
mejor
Admite args por omisión, multiples retornos y pueden pasarse como arg a otras funciones
Paradigmas
Fail fast, return early: probar errores al inicio, muchos puntos de salida, fácil de leer y depurar y de
encontrar lo que se quiere hacer
Single entry, signle exit: unico punto de entrada y salida (un return), prueba errores encadenados,
genera indentación (if if if if por cada error posible), fácil determinar donde sale la función
Módulos
Importar con import. Si esta en la misma carpeta se pone solo el nombre del archivo sino el path
Formas de importar
Import modulo1
Import modulo1 as mod (modifica el nombre del modulo a mod y ahora se invoca así)
From modulo1 import * (importa todas las variables o funciones sin necesidad de invocar de la
forma <mod>.<nombre>, puede haber colisión de nombres)
Modulos comunes: math, random, numpy as np, pandas as pd, matplotlib.pyplot as plt
Función main
Cuerpo principal del programa. Sin main interpreta todo lo de fuera de las funciones como main,
con def main(): se ejecuta solo main() al invocarla. Se ejecuta solo en el archivo en que esta
30/03/23
Secuencias: estructura de datos que agrupa varios elementos. Tienen orden, se puede iterar sobre
ellos, se pueden obtener los elementos directamente, soportan operaciones comunes.
Cadenas
Tuplas
Listas
Índices negativos: [-len(secuencia),-1] (tanto en positivos como en negatvos no se puede más alla
de su longitud de 0 a len o de 0 a -len)
Mutabilidad: solo en listas (al cambiar un string o tupla, se destruye la antigua y se crea una nueva
con un nuevo lugar en memoria, al cambiar una lista no se cambia el lugar de la memoria)
Secuencia[int:int:int] (desde que índice, hasta cual (no incluye el último) (se puede omitir para
tomar todos), paso)
05/04/23
Y en iteraciones
Funciones comunes: len, min, max, count, conversiones, index, find (solo en cadenas, no devuelve
error si no esta), upper, lower, title, Split(delimitador), join(delimitador), isalpha, isalnum,
isdecimal, isupper, islower, append, remove, insert, pop, extend, copy, replace
Listas de comprensión:
Diccionarios
Key – value
Operaciones:
Borrar: del[key]
Funciones: keys(), values(), ítems(), get(key) (retorna el valor de esa clave), pop(key)
Diccionarios de compresión:
Def usar_variables(x,*arg_values):
Print(values)
Doble asterisco: **args: se permiten multiples parámetros con un nombre explícito: (estructura de
un diccionario dentro de los parámetros de la función, valores por default)
Print(key, value)
Manejo de archivos
Codigo mediante el cual se le asigna un número a símbolos y caracteres alfanuméricos (ya que las
maquinas solo entienden números)
Archivos
Secuencia de datos almacenados en memoria, identificado por nombre a nivel de usuario (la
extensión es parte del nombre), el SO nos da funciones para usarlo
Archivos binarios: no es legible por una persona (ej: program.exe), la info se interpreta a
nivel de bit o byte (visor de archivos lo ve de forma determinada)
Archivo de texto: datos son todos caracteres ASCII/Unicode, no incluyen info como tipo de
letra, cursiva, negrita, no necesito software especializado, solo un editor de texto plano,
tienen líneas separadas por el ‘\n’ o ‘\r\n’ (ej: archivos.py,.txt,.csv), la extensión es por
comodidad, para identificarlos
Apertura de archivos
Cierre de archivos
Archivo_x.close()
Línea1 = Archivo_x.readline()
Línea2 = Archivo_x.readline()
Lista_De_lineas = Archivo_X.readlines()
13/04/23
SEGUNDO BIMESTRE
08/05/23
Algoritmos de búsqueda
Lineal:
Busqueda lineal con corte: (El orden de una cadena es alfabético, un caracter es menor a otro de
acuerdo a su valor Unicode 'aardonyx'<'abelisaurus' Es True), si el elemento no esta se evita
recorrer el resto.
devolver i
devolver -1
devolver -1
En búsqueda binaria, si largo N = 2k, se necesitan k pasos en total. Para expresar k en función de N,
tomamos logaritmo y k = log2(N) entonces T(N) es proporcional a log2(N) (crece logarítmicamente y
no linealmente)
Big O Notation: T(N) como función, el algoritmo se asegura ser mejor o igual que el anterior
diciendo que pertenece al conjunto O(vieja funcion). O = orden
10/05/23
Propiedades de Big O: multiplicar por una constante o sumarle una constante no modifica el
orden, grado de mayor peso
Lineal: O(n)
O(n2) O(n log(n))
Algoritmos de ordenamiento
Utilizar la función sort. Complejidad temporal de sort?, tiene que pasar una vez por cada
elemento, por lo que la complejidad temporal es peor o igual a la búsqueda lineal tradicional
Ordenamiento Bogo
Repetir ciclo:
Retornar lista
Sino
Mezclar lista
Mejor caso: solo requiere recorrer n elementos (O(n)), Peor caso: nunca se comprueba,
complejidad indefinida
Buscar el minimo -> Intercambiar el minimo con el primero -> Definir nueva lista excluyendo los
ordenados -> Repetir
Para j entre [0, n-2]
Comenzar comparando dos elementos de la izq -> Si el de la izquierda es mayor, intercambiar ->
Incrementar una posición y continuar hasta recorrer toda la lista -> Definir sublista excluyendo el
ultimo elemento de la sublista anterior -> Repetir hasta que la nueva sublista sea de largo 1
Tomar la posición 1 como referencia -> Comparar el elemento acyual con anteriores -> Insertar
elemento actual a la derecha del primer elemento menor al actual o en la posición 0-> Repetir
Actual = elemento j
K=j
K = k-1
Guardar actual en k
Bubblesort:
def bubblesort(lista):
for j in range(len(lista)):
for k in range(0,len(lista)-j-1):
if lista[k+1]< lista[k]:
11/05/23
Recursión
Recursividad es el proceso mediante el que una función se llama a si misma de forma repetida
hasta que se satisface alguna condición
Se usa en muchos aspectos. Ejemplo de la ciudadanía. (efecto infinito). Def. recursiva tiene dos
partes:
1- Caso recursivo: resolver un problema reduciéndolo a una versión más pequeña (bucle
constante)
2- Caso base: especifica directamente el resultado para un caso particular. Garantiza que el
algoritmo recursivo termine y se resuelva en un tiempo finito (final)
Algorítmicamente: nos permite dividir el problema y resolver, semánticamente: usar una función
que se invoca a sí misma.
Def func(x):
func(x)
func(3)
(infinito)
Pila (stack)
1- Cuando se llama una función se crea un nuevo marco de pila o stack frame
2- Cuando finaliza el stack frame desaparece
3- Si se invoca una dentro de otra. Los stack frames se van acumulando
4- A medida que las funciones terminan se libera primer el stack frame añadido más reciente
y por último el más antiguo
5- El ultimo que entra es el primero que sale
Pila en recursión
Def func(n):
Print(n)
Func(n-1)
Func(3)
If n>0:
Print(n)
Func2(n-1)
Func2(5)
Caso base en el que concluye la recursión: cuando n deja de ser positivo (0), a partir de ahí se
borran los frames acumulados previamente
Def func2(n):
If n>0:
Func2(n-1)
Print(n)
Func2(5)
Memoization
Llevar registro de lo que se va calculando y ahorrarse ese cáclulo para el futuro: diccionarios
17/05/23
Merge Sort
o Se aplica el algoritmo merge sort recursivamiente a cada mitad para obtener dos sublistas
ordenadas
o Se obtiene la lista total ordenada fusionando ordenadamente las dos sublistas
Def mergesort(lista):
If len(lista)<2:
Return lista
Else:
Medio = len(lista)//2
Lista1_ord = merge_Sort(lista[:medio])
Lista2_ord = merge_Sort(lista[medio:])
I,j = 0,0
Result = []
If (lista1[i]<lista2[j]):
Result.append(lista1[j])
I+=1
Else:
Result.append(lista2[j])
J+=1
Result += lista1[i:]
Result += lista2[j:]
Return result
Complejidad temporal
T(N) = 2 T(N/2) + cn
[diapo 2 a la k y big O]
POO
Se puede crear un objeto, asignar una instancia a una variable, interactuar con el objeto y destruir
el objeto
Un caso general, una plantilla para crear objetos (instancias, casos particulares)
Class <nombre>:
Self.atributo1 = <atrib1>
Self.atributo2 = <atrib2>
Self.__atributoEncapsulado = <atrib3>
<sentencias>
Def getAtributo(self):
Return self.atributo1
Getter y setter
Característica = Variable.getAtributo()
18/05/23
POO
Objeto mutable
[diapo]
Métodos especiales
Constructor:
__init__(self, atributos)
Aritméticos:
__add__(self, other) -> self + other: suma objetos, para eso hay que definir dentro del
método cual será la operación de suma y su retorno [diapo]
__sub__(self, otro) -> self – otro: resta objetos, hay que definir dentro del método como
se realiza la resta entre esos objetos
__mul__(self, otro) -> self * otro: “”
__truediv__(self, otro) -> self / otro: “”
Comparación
Representación
Secuencias personalizadas
len(obj) -> __len__(self): determina que retorna cuando se le hace len al objeto [diapo]
Obj[ítem] -> __getitem__(self, item): permite definer el comportamiento del objeto
cuando se accede a un elemento de ese objeto [diapo]
Obj[item] -> __setitem__(self, item): permite definer el comportamiento del objeto
cuando se agrega un elemento a ese objeto
Destrucción
Del(obj) -> __del__(self): además de borrar el objeto, define que hacer cuando se lo borra
31/05/23
Programacion defensiva
Documentar funciones
Modularizar programas
Validar entradas y salidas
Testing
Diseñar pruebas: luego el código que las pasa (TDD) o al revés, cada entrada una salida
Tipos de pruebas:
1. Test unitarios: valida cada pieza del programa, cada función
2. Test de regresión: se agregan al encontrar un bug, atrapan bugs que fueron
solucionados y se reintrodujeron
3. Test de integración: prueba el funcionamiento general del programa
Entradas: Partición natural: ¿cuáles son los extremos del problema? Casos de borde
Pruebas aleatorias: no hay una partición evidente, más pruebas más
probabilidadde saber, es un último recurso
Enfoques:
1. Black box testing: diseñamos pruebas sin mirar el código, mejor si lo hace otra
persona no el developer, se pueden reutilizar las pruebas si el código cambia,
avanza por especificación, prueba las particiones naturales y las condiciones de
borde
2. Glass box testing: miramos el código para diseñar pruebas, probamos ramas de
ejecución (ifs); ciclos fors y ciclos whiles, es “de camino completo” si recorre todas
las posibles ramas, si pasa por todas las líneas es Coverage 100% o path complete,
contras: puede pasar por ciclos cualquier cantidad de veces y Coverage < 100%
Debugging
Propagación de excepciones: error en una función f se propága en las funciones en las que se
llama a f
¿Qué hacer cuando hay error? Que falle silenciosamente (reemplazar valores de entrada para los
que si funciona), devolver códigos de error (-1 por ejemplo), frenar la ejecución (lanzando
excepciones)
try, except
Manejo completo
Try:
Except:
raise <nombre_excepcion>(<mensaje>)
Excepción de tipo assertion (para encontrar bugs apenas son ingresados, como suplemento al
testing, para validación de entradas) (se pueden deshabilitar los asserts con un comando en
Introducción a C
[diapo]
#include <stdio.h>
Int main(void)
puts(“hola mundo”);
return 0;
Ejecutar: $./ejecutable
01/06/23
<tipo> <variable>;
Definir constantes
Operadores
Incluye las def de la biblioteca estándar de C, se debe incluir inicialmente en el código con #define
Operaciones built in
%<formato> = %i, %c (char), %hd (short), %s (char *), %f segun el tipo, x e y tomarán el valor
respectivamente
Scanf(“%d”, &n);
Estructuras de control
If (<condición_1>){
<sentencia_1>;
Else if (){}
Else{}
Switch:
Switch(<valor>){
<sentencias 1>;
Break
<sentencias 2>;
break
default:
<sentencias3>;
Ciclos
While (<condición>){
<sentencia1>
For(<exp_inicial>;<exp_condicion>;<exp_iteracion>){
<sentencia1>
Rand y srand
#include <stdlib.h>
Rand()
Srand()
Da una semilla para esa generación aleatoria. Si no se fija una semilla por defecto será 1. Siempre
genera lo mismo aleatoriamente con la misma semilla
#include <time.h>
Time()
Permite obtener el tiempo actual en segundos, desde el 1 de enero de 1970. Es útil utilizar el
tiempo actual como semilla
07/06/23
Funciones en C
<sentencia_1>
<sentencia_2>
Return <valor_retorno>;
Int main(void){
Return 0;
Function utilizada en main debe ser definida antes de ser utilizada. O al menos ser declarada antes
sin asignación de variables y luego ser asignada luego del main()
Printf(“Hola\n”);
}
Variables de alcance local: las variables definidas dentro de una función son locales y corresponen
al ámbito de esa función (luego desaparecen al terminar la llamada)
Variables de alcance global (no tan buena práctica): definirla afuera de las otras funciones, afuera
del main
Modularizacion
Proceso de compilación
[diapo]
Comandos de compilación
1)Compilar
2)Ejecutar
$./ejecutable
En el ejemplo, se debe agarrar main.c y modulo.c y hacer el proceso de compilación con ambos a
la vez. Si no no tengo definidas mis funciones
1)Compilar
2)Ejecutar
$./ejecutable
Conversión de tipos
Cuando tengo distintos tipos y hago operaciones, se guarda en el tipo más grande según jerarquía:
1. Doublé
2. Flout
3. Unsigned long
4. Long
5. Unsigned int
6. Int
[diapo de ejemplo]
Int x = 3
Int y = 2
Float z;
Z = (float)x/y;
08/06/23
Arrays
Float array1[10];
Array1[0] = 1.2;
Si no esta el \0 imprime infinitamente los caracteres en memoria sin frenar, (con %s)
Punteros
Variable que guarda una dirección de memoria. Necesario apuntar el tipo del dato que será
apuntado
<tipo> * <puntero>;
Manipulacióon de punteros
*<puntero> = <valor>; (copia el valor de una variable en la dirección que apunta el puntero)
Int x = 5;
Int *p; (dirección de memoria que a punta a una variable de tipo entero
Char *s;
Printf(…,*p)
P = a;
Printf(…, p[0])
Si queremos que una función nos pueda devolver varios resultados se pueden devolver por
referencia en lugar de por valor:
<sentencias
*y1 = expresión;
Función(*var){
*var = jdaospn
N = sizeof(vec)/sizeof(int)
Longitud = strlen(<cadena>);
Memcpy(<dest>,<src>,n);
Char dest[20]
Strcmp, devuelve 0 si las cadenas son iguales en orden, o <0 o >0 según si la primera es menor o
mayor a la segunda
Strcat, concatena una cantidad especifica de caracteres de una cadena de origen al final de una
cadena de destino. Siempre que tenga espacio en el primer string
Strcat(“hola”,”, mundo”);