2492 lines
59 KiB
Markdown
2492 lines
59 KiB
Markdown
**Ir a:**
|
|
[*Repositorio*](https://gitea.kickto.net/devfzn/Apuntes_Python),
|
|
[*Modulo 1*](https://gitea.kickto.net/devfzn/Apuntes_Python/src/branch/master/01_curso/Modulo_1#modulo-1-python-basico),
|
|
[*Modulo 3*](https://gitea.kickto.net/devfzn/Apuntes_Python/src/branch/master/01_curso/Modulo_3#modulo-3-python-basico)
|
|
|
|
## Modulo 2 - Python basico
|
|
|
|
#### [Indice](#modulo-2-python-basico)
|
|
- [Strings Format](#strings)
|
|
- [Decodificadores de strings](#decodificadores-de-strings)
|
|
- [Función join](#join)
|
|
- [Metodos de Strings](#metodos-de-strings)
|
|
- [Constantes de la libreria string](#constantes-que-define-la-libreria-string)
|
|
- [Formateo de strings](#formateo-de-strings)
|
|
- [Fecha y Hora](#fechas-date)
|
|
- [Datetime](#datetime-hora-y-fechas)
|
|
- [Conversion a string](#tiempo-a-string)
|
|
- [Excepciones](#excepciones)
|
|
- [Excepcion personalizada](#excepción-personalizada)
|
|
- [Context manager](#context-manager)
|
|
- [Manejo de excepción IndexError](#manejo-de-excepción-indexerror)
|
|
- [Otro ejm. excepción personalizada](#ejemplo-de-excepción-personalizada)
|
|
- [Input/Output strings](#input-output-string)
|
|
- [Leer y escribir archivos](#leer-y-escribir-archivos)
|
|
- [Leer Archivos](#leer-archivos)
|
|
- [Escribir en archivos](#escribiendo-en-archivos)
|
|
- [Leer, Escribir CSV](#leer-y-escribir-csv)
|
|
- [Datos estructurados JSON](#json)
|
|
- [Matrices, Conjuntos](#matrices)
|
|
- [Listas, Pilas, Colas, Stacks](#listas)
|
|
- [Funciones](#algunas-funciones)
|
|
- [Listas como Pilas](#listas-como-pilas)
|
|
- [Listas como Colas](#listas-como-colas)
|
|
- [Listas por comprensión](#listas-por-comprension)
|
|
- [Buscar en lista](#buscar-elemento-en-una-lista)
|
|
- [Listas por comprensión 2](#comprension-de-listas-2)
|
|
- [Tuplas y secuencias](#tuplas)
|
|
- [Diccionarios](#diccionarios)
|
|
- [Operaciones sobre diccionarios](#las-operaciones-principales-son)
|
|
- [Acceso a elementos](#acceso-a-elementos-por-claves)
|
|
- [Metodos](#metodos-en-los-diccionarios)
|
|
- [Iterando diccionarios](#iterando-diccionarios)
|
|
- [Resumen](#resumen-diccionarios)
|
|
- [Generadores](#generadores)
|
|
- [Ejemplos](#uso-de-generadores)
|
|
- [Decoradores](#decoradores)
|
|
- [Ejercicios](#ejercicios-modulo-2)
|
|
- [Verdurería](#verdureria)
|
|
- [El juego del Gato](#el-gato)
|
|
|
|
----
|
|
|
|
|
|
## Strings
|
|
|
|
Cadenas(*secuencia*) de caracteres
|
|
```python
|
|
|
|
'Str' "Str"
|
|
|
|
"""
|
|
Para multilinea usar 3 pares de cualquier tipo
|
|
"""
|
|
|
|
a_str = 'Hola Mundo!'
|
|
|
|
# * Acceso a caracter según posición
|
|
a_str[0] # retorna H
|
|
a_str[-1] # retorna !
|
|
|
|
# * Slicinf de un string
|
|
a_str[:4] # retorna HOLA
|
|
a_str[5:9] # retorna Mundo
|
|
|
|
# * Longitud String
|
|
len(a_str) # retorna 11
|
|
```
|
|
|
|
Caracter de escape **` \ `**, para acceder a las secuencias de escape comunes.
|
|
Ej.: **` \' `**, **` \" `**, **` \n `**, **` \r `**, **` \t `**.
|
|
|
|
|
|
### Decodificadores de strings
|
|
|
|
ej. codificar (de unicode a un byte array con codif. determinada)
|
|
decodificar ( de un byte array con una codif. determ. a unicode)
|
|
```python
|
|
a_str = 'Otoño'
|
|
|
|
# utf-8 encode
|
|
str_codific = a_str.encode('utf-8') # Respuesta: b'Oto\\xc3\\xb1o'
|
|
|
|
# utf-8 decode
|
|
str_codific.decode('utf-8') # Respuesta: 'Otoño'
|
|
|
|
# Unicode es la ley
|
|
# ASCCI no tiene estos caracteres.. lo cual da error
|
|
# str2 = "áéíóú"
|
|
# str3 = str2.encode('ascii')
|
|
```
|
|
|
|
|
|
### Strings y variables
|
|
```python
|
|
nombre = "Reberte"
|
|
"Hola %s" % nombre
|
|
# 'Hola Reberte'
|
|
|
|
"Un nro. %d" % 5
|
|
# 'Un nro. 5'
|
|
|
|
"Nr0. de 2 digitos %02d" % 5
|
|
# 'Nr0. de 2 digitos 05'
|
|
|
|
"Un float %f" % 6.4
|
|
# 'Un float 6.400000'
|
|
|
|
"Float 2 digitos %.2f" % 2.54
|
|
# 'Float 2 digitos 2.54'
|
|
|
|
"Hola %(name)s" % {'name': nombre }
|
|
# 'Hola Reberte'
|
|
|
|
"Hola {}".format(nombre)
|
|
# 'Hola Reberte'
|
|
|
|
"{0} + {1} es {2}".format(7,2,7+2)
|
|
# '7 + 2 es 9'
|
|
```
|
|
|
|
|
|
### join
|
|
|
|
Construye strings concatenando lista de valores
|
|
```python
|
|
' ',join(["Hola", nombre])
|
|
', '.join(['1','2','3','4'])
|
|
```
|
|
|
|
## Metodos de Strings
|
|
python -i
|
|
`>>> help(str)`
|
|
```
|
|
METODOS DE LOS STRINGs
|
|
|
|
NOMBRE ej. Resultado
|
|
|
|
capitalize 'word'.capitalize() 'Word'
|
|
center 'word'.center(10,'*') '**word**'
|
|
count 'word'.countd(d) 1
|
|
encode 'word'.encode('utf-8') b'word'
|
|
endswith 'word'.endswith('d') True
|
|
find 'wordw'.find('w') 0
|
|
rfind 'wordw'.rfind('w') 4
|
|
format 'Hola {}'.format('Elmo') 'Hola Elmo'
|
|
index 'wordw'.index('w') 0
|
|
rindex 'wordw'.rindex('w') 4
|
|
isalnum 'word'.isalnum() True
|
|
isalpha 'word'.isalpha() True
|
|
isdecimal '10'.isdecimal() True
|
|
isdigit '10'.isdigit() True
|
|
islower 'woRd'.islower() False
|
|
isnumeric '23'.isnumeric() True
|
|
isprintable 'word'.isprintable() True
|
|
isspace ' '.isspace() True
|
|
islitle 'Two Words'.islitle() True
|
|
isupper 'WORD'.isuper() True
|
|
lower 'woRd'.lower() 'word'
|
|
replace 'woRd'.replace('R','rl') 'world'
|
|
split '1-2-3-4'.split('-') ['1', '2', '3', '4']
|
|
startwith 'word'.startwith('w') True
|
|
strip ' word '.strip() 'word'
|
|
lstrip
|
|
rstrip
|
|
ljust 'word'.ljust(8) 'word '
|
|
rjust
|
|
swapcase 'WoRd'.swapcase() 'wOrD'
|
|
title 'a title'.title() 'A Title'
|
|
upper 'word'.upper() 'WORD'
|
|
zfill 'word'.zfill(10) '000000word'
|
|
rindex 'word'.
|
|
```
|
|
|
|
|
|
#### Constantes que define la libreria string
|
|
|
|
- **ascii_letters** :
|
|
La concatenación de las letras minúsculas y letras mayúsculas.
|
|
`abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ`
|
|
|
|
- **ascii_lowercase** :
|
|
Las letras minúsculas. `abcdefghijklmnopqrstuvwxyz`
|
|
|
|
- **ascii_uppercase** :
|
|
Las letras mayúsculas. `ABCDEFGHIJKLMNOPQRSTUVWXYZ`
|
|
|
|
- **digits** :
|
|
Los dígitos del sistema decimal. `0123456789`
|
|
|
|
- **hexdigits** :
|
|
Los dígitos del sistema hexadecimal. `0123456789abcdefABCDEF`
|
|
|
|
- **octdigits** :
|
|
Los dígitos del sistema octal. `01234567`
|
|
|
|
- **punctuation** :
|
|
Símbolos de puntuación. `!"#$%&\'()*+,-./:;<=>?@[\\]^_\`{|}~`
|
|
|
|
- **printable** :
|
|
Todos los caracteres considerados imprimibles.
|
|
```
|
|
0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJK
|
|
MNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~
|
|
\t\n\r\x0b\x0c
|
|
```
|
|
|
|
- **whitespace** :
|
|
Todos los caracteres considerados espacios en blanco. `\t\n\r\x0b\x0c`
|
|
|
|
### Formateo de strings
|
|
```python
|
|
name = 'Reberte'
|
|
print('Hola {}'.format(name))
|
|
# 'Hola Reberte'
|
|
|
|
print('{} + {} = {}'.format(2,5,7))
|
|
# '2 + 5 = 7'
|
|
|
|
print('{1} + {2} = {0}'.format(7,5,2))
|
|
# '5 + 2 = 7'
|
|
|
|
print('Hola {nombre}'.format(nombre = name))
|
|
# 'Hola Reberte'
|
|
|
|
|
|
tupla = 4, 3
|
|
type(tupla)
|
|
# <class 'tuple'>
|
|
|
|
print('X: {0[0]}; Y: {0[1]}'.format(tupla))
|
|
# 'X: 4; Y: 3'
|
|
|
|
print('{0:f} + {1:f} = {result:f}'.format(2, 5, result=7))
|
|
'2.000000 + 5.000000 = 7.000000'
|
|
|
|
print('{0:.3f} + {1:.3f} = {result:.3f}'.format(2, 5, result=7))
|
|
# '2.000 + 5.000 = 7.000'
|
|
|
|
print('{:d}'.format(25))
|
|
# '25'
|
|
|
|
# '{:d}'.format(25.5)
|
|
# Traceback (most recent call last):
|
|
# File "<stdin>", line 1, in <module>
|
|
# ValueError: Unknown format code 'd' for object of type 'float'
|
|
|
|
print('{:.0f}'.format(25.50))
|
|
# '26'
|
|
|
|
print('Hola {nombre:16}'.format(nombre=name))
|
|
# 'Hola Reberte '
|
|
|
|
print('Hola {nombre:<16}'.format(nombre=name))
|
|
# 'Hola Reberte '
|
|
|
|
print('Hola {nombre:>16}'.format(nombre=name))
|
|
# 'Hola Reberte'
|
|
|
|
print('Hola {nombre:^16}'.format(nombre=name))
|
|
# 'Hola Reberte '
|
|
|
|
print('Hola {nombre:*^16s}'.format(nombre=name))
|
|
# 'Hola ****Reberte*****'
|
|
```
|
|
|
|
----
|
|
|
|
|
|
## Fechas (date)
|
|
|
|
```python
|
|
import datetime
|
|
|
|
# date object
|
|
# 18-Jun-20
|
|
fecha = datetime.date(2020, 6, 18)
|
|
|
|
fecha.year # 2020
|
|
fecha.month # 6
|
|
fecha.day # 18
|
|
|
|
fecha.weekday() # Lunes 0 -> Domingo 6
|
|
fecha.isoweekday() # Lunes 1 -> Domingo 7
|
|
fecha.isocalendar() # tuple( año, semana, dia semana)
|
|
fecha.isoformat() # YYY-MM-DD
|
|
```
|
|
|
|
### timedelta()
|
|
```python
|
|
hoy = datetime.date.today()
|
|
ayer = hoy - datetime.timedelta(days=1)
|
|
|
|
delta = hoy - ayer # 1 day, 0:00:00
|
|
```
|
|
|
|
### Datetime ( hora y fechas )
|
|
```python
|
|
|
|
fecha_hora = datetime.datetime(2020, 12, 2, 9, 15, 30)
|
|
# (YYYY, MM, D, h, m , s )
|
|
|
|
print(fecha_hora.date()) # 2020-12-02
|
|
|
|
# formato local
|
|
ahora = datetime.datetime.now()
|
|
|
|
# UTC
|
|
ahora = datetime.datetime.utcnow()
|
|
```
|
|
|
|
### Tiempo a string
|
|
```python
|
|
hora = datetime.time(10, 40, 35)
|
|
hora.hour
|
|
hora.minute
|
|
hora.second
|
|
hora.microsecond
|
|
|
|
fecha = datetime.datetime(2020, 4, 30, 11, 25, 30)
|
|
```
|
|
|
|
- Conversion DateTime a String # strftime
|
|
- `fecha.strftime('%Y-%m-%d')`
|
|
- `fecha.strftime('%Y-%m-%d' T%H:%M:%S')`
|
|
- `fecha.strftime('%Y-%m-%d %H:%M:%S')`
|
|
|
|
- Conversion String a DateTime # strptime
|
|
- `fecha.strptime('2020-01-10', '%Y-%m-%d')`
|
|
- `fecha.strptime('2020-01-10 T11:30:25', '%Y-%m-%d' T%H:%M:%S')`
|
|
- `fecha.strptime('2020-01-10 11:30:25','%Y-%m-%d %H:%M:%S')`
|
|
|
|
----
|
|
|
|
|
|
## Excepciones
|
|
Hay principalmente 2 tipos de errores: de sintaxis y excepciones
|
|
```python
|
|
while True :
|
|
try:
|
|
x = int(input('Excepcion si no se ingresa un ENTERO ->'))
|
|
break
|
|
except ValueError:
|
|
print('Se puede salir con Ctrl-C')
|
|
```
|
|
|
|
```python
|
|
while True :
|
|
try:
|
|
x = int(input('Excepcion si no se ingresa un ENTERO ->'))
|
|
break
|
|
except (ValueError, KeyboardInterrupt):
|
|
print('Ya, no se puede salir y con Ctrl-C')
|
|
```
|
|
|
|
```
|
|
... except (RuntimeError, TypeError, NameError):
|
|
... pass
|
|
```
|
|
```python
|
|
class B(Exception):
|
|
pass
|
|
|
|
class C(B):
|
|
pass
|
|
|
|
class D(C):
|
|
pass
|
|
|
|
for cls in [B, C, D]:
|
|
try:
|
|
raise cls()
|
|
except D:
|
|
print("D", D)
|
|
except C:
|
|
print("C", C)
|
|
except B:
|
|
print("B", B)
|
|
print('')
|
|
```
|
|
|
|
```python
|
|
for cls in [B, C, D]:
|
|
try:
|
|
raise cls()
|
|
except B:
|
|
( print("B")
|
|
except D:
|
|
print("D")
|
|
except C:
|
|
print("C")
|
|
print('')
|
|
```
|
|
|
|
```python
|
|
import sys
|
|
|
|
try:
|
|
f = open('mifile.txt')
|
|
s = f.readline()
|
|
i = int(s.strip())
|
|
except OSError as err:
|
|
print("Error OS: {0}".format(err))
|
|
except ValueError:
|
|
print("No pude convertir el dato a entero.")
|
|
except:
|
|
print("Error inesperador: ", sys.exc_info()[0])
|
|
raise
|
|
|
|
#for arg in sys.argv[1:]:
|
|
# try:
|
|
# f = open(arg, 'r')
|
|
# except OSError:
|
|
# print('no pude abrir', arg)
|
|
# else:
|
|
# print(arg, 'tiene', len(f.readlines()), 'lineas')
|
|
# f.close()
|
|
```
|
|
|
|
*python -i*
|
|
```python
|
|
try:
|
|
raise Exception('carne', 'huevos')
|
|
except Exception as inst:
|
|
print(type(inst))
|
|
print(inst.args)
|
|
print(inst)
|
|
#x, y = inst
|
|
#print('x: ',x ,'y: ',y)
|
|
```
|
|
```python
|
|
>>> raise RuntimeError('Error error bip bap bip! no computa! bip bap!')
|
|
Traceback (most recent call last):
|
|
File "<stdin>", line 1, in <module>
|
|
RuntimeError: Error error bip bap bip! no computa! bip bap!
|
|
```
|
|
|
|
### Relanzando la excepción para ser manejada en otro contexto.
|
|
```python
|
|
try:
|
|
raise NameError('y bueno un error común')
|
|
except NameError:
|
|
print('ee.. salto un except!')
|
|
raise
|
|
```
|
|
|
|
-----
|
|
|
|
### Excepción Personalizada
|
|
|
|
```python
|
|
class Error(Exception):
|
|
"""Clase base para excepciones en el módulo"""
|
|
pass
|
|
```
|
|
|
|
### Acciones de limpieza
|
|
```python
|
|
class EntradaError(Error):
|
|
"""Excepción lanzada por error en las entradas.
|
|
|
|
|
|
Atributos:
|
|
expresion -- expresión de entrada en la que ocurre el error
|
|
mensaje -- explicación del error
|
|
"""
|
|
|
|
def __init__(self, expresion, mensaje):
|
|
self.expresion = expresion
|
|
self.mensaje = mensaje
|
|
```
|
|
```python
|
|
class TransicionError(Error):
|
|
"""Lanzada por operación que intenta transición de estado no permitida.
|
|
|
|
|
|
Atributos:
|
|
previo -- estado al conmenzar la transición
|
|
siguiente -- nuevo estado intentado
|
|
mensaje -- explicación de transición no permitida
|
|
"""
|
|
|
|
def __init__(self, previo, siguiente, mensaje):
|
|
self.previo = previo
|
|
self.siguiente = siguiente
|
|
self.mensaje = mensaje
|
|
```
|
|
|
|
|
|
### finally
|
|
```python
|
|
try:
|
|
#raise KeyboardInterrupt
|
|
pass
|
|
finally:
|
|
print('hasta pronto!')
|
|
|
|
|
|
def dividir(x, y):
|
|
try:
|
|
res = x / y
|
|
except ZeroDivisionError:
|
|
print("¡división por cero!")
|
|
else:
|
|
print("el resultado es: ", res)
|
|
finally:
|
|
print('bloque finally')
|
|
|
|
dividir(2, 1)
|
|
dividir(2, 0)
|
|
```
|
|
### Context manager
|
|
Esta sentencia deja el archivo abierto tras usarlo
|
|
```python
|
|
for linea in open("miarchivo.txt"):
|
|
print(linea, end="")
|
|
|
|
# with asegura liberar el recurso tras su uso
|
|
with open("miarchivo.txt") as f:
|
|
for linea in f:
|
|
print(linea, end="")
|
|
```
|
|
### Manejo de excepción IndexError
|
|
```python
|
|
def find(elemento, lista):
|
|
"""Devuelve el indice del @elemento en @lista.
|
|
Si no lo encuentra retorna -1
|
|
"""
|
|
index = 0
|
|
while True:
|
|
try:
|
|
if lista[index] == elemento:
|
|
return index
|
|
except IndexError:
|
|
return -1
|
|
index += 1
|
|
|
|
# ejemplos de find
|
|
print(find(4,[2,3,4,5])) # 2
|
|
print(find(2,[2,3,4,5])) # 0
|
|
print(find(9,[2,3,4,5])) # -1
|
|
```
|
|
|
|
### Ejemplo de excepción personalizada
|
|
```python
|
|
class MiExcepcion(Exception):
|
|
"Excepcion personalizada"
|
|
pass
|
|
|
|
def fun_ejm(numero):
|
|
if numero <= 0:
|
|
raise MiExcepcion("nro negativ. o cero")
|
|
return 1/numero
|
|
|
|
print(fun_ejm(10))
|
|
print(fun_ejm(-4))
|
|
```
|
|
----
|
|
|
|
## Input Output String
|
|
|
|
- **repr(), rjust()**
|
|
```python
|
|
for x in range(1, 11):
|
|
print(repr(x).rjust(2), repr(x * x).rjust(3), repr(x * x * x).rjust(4))
|
|
|
|
# 1 1 1
|
|
# 2 4 8
|
|
# 3 9 27
|
|
# 4 16 64
|
|
# 5 25 125
|
|
# 6 36 216
|
|
# 7 49 343
|
|
# 8 64 512
|
|
# 9 81 729
|
|
# 10 100 1000
|
|
|
|
```
|
|
```python
|
|
for x in range(1, 11):
|
|
print('{0:2d} {1:3d} {2:4d}'.format(x, x * x, x * x * x))
|
|
|
|
# 1 1 1
|
|
# 2 4 8
|
|
# 3 9 27
|
|
# 4 16 64
|
|
# 5 25 125
|
|
# 6 36 216
|
|
# 7 49 343
|
|
# 8 64 512
|
|
# 9 81 729
|
|
# 10 100 1000
|
|
```
|
|
|
|
- **zfill()**
|
|
```python
|
|
print('12'.zfill(5), end='\n' * 2)
|
|
# 00012
|
|
```
|
|
|
|
- **format()**
|
|
```python
|
|
print('Somos {}, pero otras "{}!"'.format('celestes', 'magenta'))
|
|
# Somos celestes, pero otras "magenta!"
|
|
|
|
print('Somos {1}, cantamos "{0}"'.format('aves', 'pio-pio'))
|
|
# Somos pio-pio, cantamos "aves"
|
|
|
|
print('Este {cosa} es {adjetivo}.'.format(cosa='loro', adjetivo='azul'))
|
|
# Este loro es azul.
|
|
|
|
print('Este {0} es {1}!, le pongo un {nota}'.format('color', 'muy llamativo', nota=7.456))
|
|
# Este color es muy llamativo!, le pongo un 7.456
|
|
```
|
|
|
|
**Convertir valor antes que se formatee**
|
|
```python
|
|
# !a apply()
|
|
# !s str()
|
|
# !r repr()
|
|
|
|
var = 'ratas'
|
|
print('mi yate esta lleno de {!r}.'.format(var))
|
|
# mi yate esta lleno de ratas.
|
|
```
|
|
|
|
```python
|
|
from math import pi
|
|
|
|
print('El valor de PI es aprox. {0:.3f}.'.format(pi), '\n'*2)
|
|
# El valor de PI es aprox. 3.142.
|
|
|
|
print('\n El valor de Pi es app. %.2f.' % pi)
|
|
# El valor de Pi es app. 3.14.
|
|
|
|
tabla = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 76789877}
|
|
for nombre, telefono in tabla.items():
|
|
print('{0:8} ==> {1:8d}'.format(nombre, telefono))
|
|
# Sjoerd ==> 4127
|
|
# Jack ==> 4098
|
|
# Dcab ==> 76789877
|
|
|
|
print('\n', 'Jack: {0[Jack]:d}; Sjoerd: {0[Sjoerd]:d}; '
|
|
'Dcab: {0[Dcab]:d}'.format(tabla))
|
|
# Jack: 4098; Sjoerd: 4127; Dcab: 76789877
|
|
|
|
print('\nJack: {Jack:d}; Sjoerd: {Sjoerd:d}; '
|
|
'Dcab: {Dcab:d}'.format(**tabla))
|
|
# Jack: 4098; Sjoerd: 4127; Dcab: 76789877
|
|
```
|
|
|
|
### Leer y escribir archivos
|
|
|
|
```python
|
|
mi_file = open('nombre_archivo', 'modo')
|
|
-r read (default)
|
|
-r+ read/write
|
|
-w write
|
|
-a append
|
|
-x ?
|
|
```
|
|
|
|
- **read()**
|
|
```python
|
|
# El context manager cierra el archivo despues de usarlo
|
|
with open('archivo') as f:
|
|
datos_leidos = f.read()
|
|
```
|
|
|
|
- **readline()**
|
|
lee linea a linea
|
|
|
|
- **f.close()**
|
|
cierre de archivo aribitrario.
|
|
|
|
```python
|
|
print(f.closed) <-- 'True' si el archivo se cerro.
|
|
|
|
list(f) ó f.readlines() <-- pare lee todas las lineas del archivo.
|
|
|
|
f.write('cadena a escribir\n')
|
|
18
|
|
|
|
s = str(valor) # valor = ('respuesta', 16)
|
|
f.write(s)
|
|
15
|
|
```
|
|
|
|
|
|
- **f.tell()**
|
|
Devuelve la posición actual en el archivo, representada como número
|
|
de bytes desde elcomienzo del archivo en modo binario y
|
|
un número opaco en modo texto.
|
|
|
|
- **f.seek()**
|
|
*python -i*
|
|
```python
|
|
f.seek(desplazamiento, desde_donde)
|
|
|
|
>>> f =open('archivodetrabajo', 'rb+')
|
|
>>> f.write(b'0123456789abcdef')
|
|
>>> f.seek(5)
|
|
# Va al sexto byte en el archivo
|
|
5
|
|
>>> f.read(1)
|
|
b'5'
|
|
>>> f.seek(-3, 2) # Va al tercer byte antes del final
|
|
13
|
|
>>> f.read(1)
|
|
b'd'
|
|
```
|
|
otros:
|
|
- isatty()
|
|
- truncate()
|
|
|
|
-----
|
|
|
|
## Leer Archivos
|
|
|
|
```python
|
|
# Abrir archivo
|
|
arch = open('./python_subprocess_bash', 'r')
|
|
|
|
# Leer contenido
|
|
arch.read()
|
|
|
|
# Cerrar el arrchivo
|
|
arch.close()
|
|
```
|
|
|
|
> **Context manager:**
|
|
> en este caso **with** abre y cierra el archivo
|
|
> **read()** lee todo el contenido del archivo
|
|
```python
|
|
with open('./python_subprocess_bash', 'r') as archivo:
|
|
print(archivo.read())
|
|
```
|
|
|
|
### Lee por linea
|
|
```python
|
|
with open('./python_subprocess_bash', 'r') as archivo:
|
|
print(archivo.readline())
|
|
```
|
|
|
|
### Genera una lista con las lineas del archivo
|
|
```python
|
|
with open('./python_subprocess_bash', 'r') as archivo:
|
|
print(archivo.readlines())
|
|
```
|
|
|
|
### Genera una lista con las lineas del archivo
|
|
```python
|
|
with open('./python_subprocess_bash', 'r') as archivo:
|
|
print(list(archivo))
|
|
```
|
|
|
|
### For recorre linea a linea
|
|
```python
|
|
with open('./python_subprocess_bash', 'r') as archivo:
|
|
for linea in archivo:
|
|
print(linea)
|
|
```
|
|
|
|
----
|
|
|
|
## Escribiendo en archivos
|
|
```python
|
|
import subprocess
|
|
arch = 'python_subprocess_bash'
|
|
|
|
with open(arch, 'w') as archivo:
|
|
archivo.write('Hola mundo')
|
|
|
|
subprocess.check_call(["cat", arch])
|
|
print('')
|
|
```
|
|
|
|
|
|
### Escribir multiples lineas.
|
|
```python
|
|
with open(arch, 'w') as archivo:
|
|
archivo.writelines(['Linea 1.\n', 'Linea 2.\n', 'Linea 3.\n', 'Linea 4.\n'])
|
|
|
|
subprocess.check_call(["cat", arch])
|
|
```
|
|
|
|
|
|
### Anexadon al final de archivo. 'a'
|
|
```python
|
|
with open(arch, 'a') as archivo:
|
|
archivo.write('!odnuM aloH')
|
|
|
|
subprocess.check_call(["cat", arch])
|
|
```
|
|
|
|
----
|
|
|
|
## Leer y escribir CSV
|
|
|
|
### Leer CSV
|
|
`csv.reader(archivo.csv)`
|
|
```python
|
|
import csv
|
|
|
|
with open('ejm.csv', 'r') as csv_arch:
|
|
reader = csv.reader(csv_arch)
|
|
for row in reader:
|
|
#print('\t'.ljust(2).join(row))
|
|
print('{0:8}\t{1:8}\t{2:8}\t{3:8}'.format(*row))
|
|
#print('{0:8}\t{1:8}\t{2:8}\t{3:8}'.format(row[0], row[1], row[2], row[3]
|
|
|
|
#print('\n', help(row)) # las filas son listas
|
|
```
|
|
|
|
### Escribir CSV
|
|
`csv.writer(arch.csv).writerow(['elementos','a','escribir'])`
|
|
```python
|
|
with open('ejm.csv', 'a') as csv_arch:
|
|
writer = csv.writer(csv_arch)
|
|
writer.writerow(['Elvira', 'Zápáté', '34467845', 'lervielpare@zumail.zen'])
|
|
```
|
|
|
|
----
|
|
|
|
## JSON
|
|
|
|
**Java Scrit Object Notation**
|
|
|
|
El módulo estandar llamado json puede tomar datos de Python con una jerarquía, y convertirlo
|
|
a representaciones de cadena de caracteres. Este proceso es llamado **serializing**.
|
|
|
|
Reconstruir los datos desde la representación de cadena de caracteres es llamado **deserializing**.
|
|
|
|
El formato JSON es comunmente usado por aplicaciones modernas para permitir intercambiar datos.
|
|
|
|
```python
|
|
import json
|
|
```
|
|
|
|
### Serializar un objeto
|
|
```python
|
|
# Transforma el mismo a una representacion de caracteres.
|
|
json.dumps([1, 2, 3])
|
|
# '[1, 2, 3]'
|
|
```
|
|
|
|
### Deserializar una cadena
|
|
```python
|
|
# Transforma la cadena a un objeto json
|
|
json.loads('[1, 2, 3]')
|
|
# [1, 2, 3]
|
|
```
|
|
|
|
### Escribir como json a un archivo
|
|
```python
|
|
with open('archivo.json', 'w') as arch:
|
|
json.dump([1, 2, 3, 4], arch)
|
|
```
|
|
|
|
|
|
### Leer un json
|
|
```python
|
|
with open('archivo.json', 'r') as arch:
|
|
print( json.load(arch) )
|
|
```
|
|
|
|
|
|
### Otro ejemplo
|
|
```python
|
|
x = [1, 'simple', 'lista']
|
|
f = open('test_file_json', 'r+')
|
|
|
|
json.dumps([1, 'simple','lista'])
|
|
|
|
# Suponiendo q f es un archivo de texto abierto para escritura:
|
|
json.dump(x, f)
|
|
f.close()
|
|
|
|
f = open('test_file_json', 'r')
|
|
# Suponiendo q f fue abierto para lectura:
|
|
print(json.load(f))
|
|
f.close()
|
|
```
|
|
|
|
----
|
|
|
|
|
|
## Matrices
|
|
|
|
Se pueden considerar como listas de listas,
|
|
lo visto en listas aplica tambien en matrices
|
|
|
|
### Definción de matriz de 3 filas y 4 columnas.
|
|
```python
|
|
matriz = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
|
|
|
|
# Acceso a elementos matriz[ fila o lista1 ] [ columna o lista2 ]
|
|
matriz[0][0]
|
|
# 1
|
|
|
|
matriz[1][2]
|
|
# 7
|
|
|
|
|
|
# Ejm. suma de matrices
|
|
def suma_matr(A, B):
|
|
"""
|
|
Suma 2 matrices.
|
|
A: len(A) == len(B), integers.
|
|
B: len(A) == len(B), integers.
|
|
returns: Matriz con resulta de la suma de
|
|
los elementos de A y B
|
|
"""
|
|
filas, colums, C = len(A), len(A[0]), []
|
|
for fila in range(filas):
|
|
fila_temp = []
|
|
for columna in range(colums):
|
|
fila_temp.append(A[fila][columna] + B[fila][columna])
|
|
C.append(fila_temp)
|
|
return C
|
|
|
|
|
|
print(suma_matr(matriz, matriz))
|
|
# [[2, 4, 6, 8], [10, 12, 14, 16], [18, 20, 22, 24]]
|
|
```
|
|
|
|
> Libreria **NumPy** para trabajar con matrices
|
|
|
|
|
|
## Conjuntos
|
|
Un conjunto esta entre llaves no tiene elementos repetidos.
|
|
```python
|
|
frutas = {'manzana', 'naranja', 'manzana', 'pera', 'naranja', 'banana', 'kiwi'}
|
|
|
|
print(frutas) #{'kiwi', 'naranja', 'manzana', 'banana', 'pera'}
|
|
|
|
print('pera' in frutas, 'yerba' in frutas) # True False
|
|
```
|
|
|
|
### Creacion de conjuntos
|
|
```python
|
|
conj_a = set()
|
|
type(conj_a) #<class 'set'>
|
|
|
|
a = set('abracadabra') #{'r', 'a', 'b', 'd', 'c'}
|
|
b = set('alacazam') #{'l', 'm', 'a', 'z', 'c'}
|
|
|
|
print('\n a =',a ,' b =',b)
|
|
```
|
|
|
|
### Operaciones de conjuntos
|
|
```python
|
|
a - b # {'d', 'b', 'r'} elementos de a menos elementos de b
|
|
a | b # {'l', 'd', 'a', 'z', 'm', 'c', 'b', 'r'} elementos de a y b
|
|
a & b # {'c', 'a'} elementos en común (INTERSECCION)
|
|
a ^ b # {'l', 'z', 'b', 'm', 'd', 'r'} elementos únicos de cada set
|
|
```
|
|
|
|
### Comprensión de conjuntos
|
|
```python
|
|
a = {x for x in 'abracadabra' if x not in 'abc'}
|
|
|
|
a.add('z')
|
|
a.remove('z')
|
|
|
|
print('\n', a)
|
|
# {'r', 'd'}
|
|
```
|
|
|
|
|
|
### Ayuda sobre la clase set
|
|
python -i `>>>help(set)`
|
|
```
|
|
class set(object)
|
|
set() -> new empty set object
|
|
set(iterable) -> new set object
|
|
|
|
Build an unordered collection of unique elements.
|
|
|
|
Methods defined here:
|
|
add(...)
|
|
Add an element to a set.
|
|
This has no effect if the element is already present.
|
|
|
|
clear(...)
|
|
Remove all elements from this set.
|
|
|
|
copy(...)
|
|
Return a shallow copy of a set.
|
|
|
|
difference(...)
|
|
Return the difference of two or more sets as a new set.
|
|
(i.e. all elements that are in this set but not the others.)
|
|
|
|
difference(...)
|
|
Return the difference of two or more sets as a new set.
|
|
(i.e. all elements that are in this set but not the others.)
|
|
|
|
difference_update(...)
|
|
Remove all elements of another set from this set.
|
|
|
|
discard(...)
|
|
Remove an element from a set if it is a member.
|
|
If the element is not a member, do nothing.
|
|
|
|
intersection(...)
|
|
Return the intersection of two sets as a new set.
|
|
|
|
(i.e. all elements that are in both sets.)
|
|
|
|
intersection_update(...)
|
|
Update a set with the intersection of itself and another.
|
|
|
|
isdisjoint(...)
|
|
Return True if two sets have a null intersection.
|
|
|
|
issubset(...)
|
|
Report whether another set contains this set.
|
|
|
|
issuperset(...)
|
|
Report whether this set contains another set.
|
|
|
|
pop(...)
|
|
Remove and return an arbitrary set element.
|
|
Raises KeyError if the set is empty.
|
|
|
|
remove(...)
|
|
Remove an element from a set; it must be a member.
|
|
If the element is not a member, raise a KeyError.
|
|
|
|
symmetric_difference(...)
|
|
Return the symmetric difference of two sets as a new set.
|
|
(i.e. all elements that are in exactly one of the sets.)
|
|
|
|
symmetric_difference_update(...)
|
|
Update a set with the symmetric difference of itself and another.
|
|
|
|
union(...)
|
|
Return the union of sets as a new set.
|
|
(i.e. all elements that are in either set.)
|
|
|
|
update(...)
|
|
Update a set with the union of itself and others.
|
|
```
|
|
|
|
----
|
|
|
|
|
|
## Listas
|
|
|
|
Permiten guardar todo tipo de objetos
|
|
```python
|
|
lista = [3, 7.5, 'Hola', 7j + 5, [1, 2]]
|
|
|
|
# Acceso mediante indexacion
|
|
lista[0] # 3
|
|
lista[2] # 'Hola'
|
|
lista[-1] # [1, 2]
|
|
|
|
# Slicing
|
|
lista[1:] # [7.5, 'Hola', (5+7j), [1, 2]]
|
|
lista[1:2] # [7.5]
|
|
lista[1:3] # [7.5, 'Hola']
|
|
lista[:2] # [3, 7.5]
|
|
lista[:] # [3, 7.5, 'Hola', (5+7j), [1, 2]]
|
|
```
|
|
|
|
### Algunas funciones
|
|
```python
|
|
|
|
# Cantidad de elementos
|
|
len(lista)
|
|
# 5
|
|
|
|
# Agrega al final
|
|
lista.append(2)
|
|
|
|
# Extiende la lista con elementos de otra lista
|
|
# "o tupla" lista.extend((1, 2))
|
|
lista.extend([3, 4])
|
|
|
|
# Insertar elemento en posición
|
|
lista.insert(4, 'Intercalado')
|
|
lista.insert(12, 'Fuera de Rango')
|
|
lista.insert(-1, 'Hacia atrás')
|
|
|
|
# Cuenta coincidencias con argumento
|
|
lista.count(3)
|
|
|
|
# Elimina el 1er elemento encontrado
|
|
lista.remove(3)
|
|
|
|
# Copia la lista superficialmente (mutable)
|
|
copia_lista = lista.copy()
|
|
|
|
# Saca ultimo elemento, o el indicado en el indice
|
|
lista.pop()
|
|
|
|
# Limpiar lista
|
|
lista.clear()
|
|
```
|
|
|
|
```python
|
|
# Lista ls
|
|
ls = [1, 2, 3, 4]
|
|
|
|
x = 1
|
|
ls.append(x)
|
|
|
|
itr = range(10)
|
|
ls.extend(itr)
|
|
|
|
i = 0 # indice
|
|
ls.insert(i, -1)
|
|
|
|
# Elimina el primer valor encontrado (error si no ecuentra)
|
|
ls.remove(3)
|
|
|
|
# Retorna y remueve según indice
|
|
ls.pop(2)
|
|
|
|
# Borrar lista
|
|
ls.clear()
|
|
|
|
ls = [1, 2, 3, 4]
|
|
x = 2
|
|
# Devuelve la posicion del primer obejto X encontrado:
|
|
# ls.index(x, desde[0], hasta[len(ls)]) [default]
|
|
ls.index(x)
|
|
|
|
# Cantidad de incidencias de x
|
|
ls.count(x)
|
|
|
|
# Ordena lista segun alguna funcion key=nombrefuncion
|
|
ls.sort(key=None, reverse=False)
|
|
|
|
# Invierte orden lista
|
|
ls.reverse()
|
|
|
|
# Copia lista equiv. ols = ls[:]
|
|
ols = ls.copy()
|
|
```
|
|
|
|
|
|
### Funciones listas y strings
|
|
Tanto para **listas (mutables)** como para **strings (inmutables)**
|
|
```python
|
|
name = 'Reberte'
|
|
|
|
lista = list(name)
|
|
|
|
# indexado
|
|
name[0]
|
|
lista[0]
|
|
|
|
# Slicing
|
|
name[:4]
|
|
lista[:4]
|
|
|
|
# len
|
|
len(name)
|
|
len(lista)
|
|
|
|
# in
|
|
'R' in name
|
|
'R' in lista
|
|
|
|
# not
|
|
'z' not in name[0]
|
|
'z' not in lista[0]
|
|
|
|
# for
|
|
for letra in name:
|
|
print(letra)
|
|
|
|
for letra in lista:
|
|
print(letra)
|
|
|
|
# String son inmutables
|
|
lista[2] = 'o'
|
|
#name[2] = '0' # TypeError
|
|
|
|
'Hola' + name
|
|
name + '!!'
|
|
name[:2] + 'to' + name[2:]
|
|
```
|
|
|
|
### Listas como pilas
|
|
Funcionamiento de "**pilas**" (apilar)
|
|
> Último en entrar, Primero en salir **FiFo**
|
|
> **LiFo** (last in first out)
|
|
|
|
```python
|
|
pila = [1, 2, 3]
|
|
|
|
# insterar elemento
|
|
pila.append(4)
|
|
pila.append(5)
|
|
|
|
# sacar elemento
|
|
pila.pop() #5
|
|
pila.pop() #4
|
|
pila.pop() #3
|
|
```
|
|
|
|
### Listas como colas
|
|
> **FiFo** (first in first Out)
|
|
> Diseñado para trabajar con ambos extremos de la "lista"
|
|
> Se usa "collections.deque"
|
|
```python
|
|
from collections import deque
|
|
|
|
cola = deque(["Javier","Jimena","Jorge"])
|
|
|
|
cola.append("Jaqueline")
|
|
cola.append("Jose")
|
|
|
|
cola.popleft() # "Javier"
|
|
cola.popleft() # "Jimena"
|
|
|
|
cola # ["Jorge","Jaqueline","Jose"]
|
|
|
|
# LISTAS COMO COLAS 2
|
|
# FiFo (First in First Out)
|
|
|
|
cola = [1, 2, 3]
|
|
|
|
cola.append(4)
|
|
cola.append(5)
|
|
|
|
cola.pop() #1
|
|
cola.pop() #2
|
|
|
|
|
|
# Colas eficientes en libreria estandar
|
|
|
|
cola = deque([1, 2, 3])
|
|
|
|
# Agregar
|
|
cola.append(4)
|
|
cola.append(5)
|
|
|
|
cola.popleft() #1
|
|
cola.popleft() #2
|
|
```
|
|
|
|
### Listas por comprension
|
|
|
|
> Usualmente, se crean para generar listas donde cada elemento es el resultado
|
|
> de aplicar una o mas operaciones a cada miembro de una secuencia o itreable
|
|
```pyhton
|
|
# Lista de Cuadrados
|
|
cuads = []
|
|
for x in range(10):
|
|
cuads.append(x**2)
|
|
|
|
# Lista por comprension
|
|
cuads2 = [x ** 2 for x in range(10)]
|
|
|
|
# Utilizando la funcion map
|
|
cuads3 = list(map(lambda x: x**2, range(10)))
|
|
|
|
lista = [-4, -2, 0, 2, 4]
|
|
|
|
# Lista por comprensión contiene los nrs. positivos de 'lista'
|
|
[x for x in lista if x >= 0] #[0, 2, 4]
|
|
|
|
# Lista con los positivos usando funcion filter [2, 4]
|
|
list(filter(lambda x: x > 0, lista))
|
|
|
|
# Pares y su cuadrado [(0, 0), (1, 1), (2, 4), (3, 9), (4, 16), (5, 25)]
|
|
[(x, x ** 2) for x in range(6)]
|
|
|
|
# Lista de pares combinados
|
|
pares = [(x, y) for x in [1, 2, 3] for y in [3, 1, 4] if x != y]
|
|
```
|
|
|
|
|
|
|
|
### Buscar elemento en una lista
|
|
```python
|
|
ls = [1, 2, 3, 4]
|
|
|
|
# Retorna el indice si encuentra el elemento
|
|
ls.index(4)
|
|
# lanza excepecion ValueError si no
|
|
# ls.index(9)
|
|
|
|
# Indicando una sublista
|
|
# ls.index(x, desde[0], hasta[len(ls)])
|
|
ls.index(4, 1)
|
|
#ls.index(4, 0, 2) # ValueError: 4 is not in list
|
|
ls.index(4, 1, 4)
|
|
```
|
|
|
|
|
|
### Metodos de ordenamiento
|
|
```python
|
|
ls = [3, 1, 2, 9, 5, 4, 7, 8, 6]
|
|
|
|
# Ordena < a >
|
|
ls.sort()
|
|
ls.sort(reverse=True)
|
|
|
|
ls = [(1, 9), (1, 3), (1, 4), (1, 2)]
|
|
ls.sort(key=lambda x: x[1])
|
|
|
|
# Revertir el orden de los elementos
|
|
ls = [3, 1, 2, 9, 5, 4, 7, 8, 6]
|
|
ls.reverse()
|
|
|
|
# Retorna lista ordenada
|
|
sorted(ls)
|
|
sorted(ls, reverse=True)
|
|
|
|
ls = [(1, 9), (1, 3), (1, 4), (1, 2)]
|
|
sorted(ls, key=lambda x: x[1])
|
|
|
|
# Ordenar según la suma de pares de elementos, en la lista en sí, ascendente (sort(default))
|
|
ls = [(6, 2), (1, 5), (2, 3), (4, 1), (5, 2), (1, 3)]
|
|
ls.sort(key=lambda x: x[0]+x[1])
|
|
```
|
|
|
|
|
|
### Comprension de listas 2
|
|
```python
|
|
# Creando una lista de los primeros 10 cuadrados matematicos
|
|
|
|
cuads = []
|
|
for x in range(10):
|
|
cuads.append(x**2)
|
|
|
|
cuads # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
|
|
|
|
# Mas eficiente:
|
|
cuads = list(map(lambda x: x**2, range(10)))
|
|
|
|
# aún mas:
|
|
cuads = [x ** 2 for x in range(10)]
|
|
```
|
|
|
|
```python
|
|
# Esta lista de comprensión combina los elementos de 2 listas
|
|
# si no son iguales
|
|
[(x, y) for x in [1, 2, 3] for y in [3, 1, 2] if x != y]
|
|
# [(1, 3), (1, 2), (2, 3), (2, 1), (3, 1), (3, 2)]
|
|
|
|
# Equivalente a:
|
|
cuads = []
|
|
for x in [1, 2, 3]:
|
|
for y in [3, 1, 4]:
|
|
if x != y:
|
|
cuads.append((x, y)) #tupla
|
|
#append recive un argumento
|
|
|
|
|
|
vec = [-4, -2, 0, 2, 4]
|
|
|
|
# Lista con valores*2
|
|
[x * 2 for x in vec] # [-8, -4, 0, 4, 8]
|
|
|
|
|
|
# Filtrar excluyendo nros. negativos
|
|
[x for x in vec if x >= 0] #[0, 2, 4]
|
|
|
|
# Aplicar funcion a elementos
|
|
[abs(x) for x in vec] #[4, 2, 0, 2, 4]
|
|
|
|
# Metodo a elemento
|
|
fruta = [' Banana ',' Murtilla ',' Tuna ']
|
|
[arma.strip() for arma in fruta] #['banana', 'mora de Logan', 'maracuya']
|
|
|
|
# Lista de Tuplas de dos elementps (nro y nro al cuadrado)
|
|
[(x, x ** 2) for x in range(6)]
|
|
# [(0, 0), (1, 1), (2, 4), (3, 9), (4, 16), (5, 25)]
|
|
|
|
# Aplanar una lista (con 2 for)
|
|
vec = [[1, 2, 3], [4, 5, 6],[7, 8, 9]]
|
|
|
|
[num for elem in vec for num in elem]
|
|
# [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
|
|
|
|
# Pueden tener expresiones complejas y funciones anidadas
|
|
from math import pi
|
|
|
|
[str(round(pi, i)) for i in range(1, 6)]
|
|
# ['3.1', '3.14', '3.142', '3.1416', '3.14159']
|
|
```
|
|
|
|
### Listas por comprension anidadas
|
|
|
|
> La expresión inicial de una comprensión de listas puede ser cualquier expresión arbitraria,
|
|
> incluyendo otra comprensión de listas.
|
|
```python
|
|
matriz =[[1, 2, 3, 4], # ej. matrix 3x4
|
|
[5, 6, 7, 8], # lista de 3 listas de largo 4
|
|
[9,10,11,12]]
|
|
|
|
# Tansponer filas y columnas:
|
|
[[fila[i] for fila in matriz] for i in range(4)]
|
|
# [[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
|
|
|
|
transp = []
|
|
for i in range(4):
|
|
transp.append([fila[i] for fila in matriz])
|
|
|
|
transp
|
|
# [[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
|
|
|
|
# es lo mismo que:
|
|
transp = []
|
|
for i in range(4):
|
|
# comprension de listas anidada
|
|
fila_tra= []
|
|
for fila in matriz:
|
|
fila_tra.append(fila[i])
|
|
transp.append(fila_tra)
|
|
|
|
transp
|
|
# [[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
|
|
|
|
|
|
# Existen funciones predefinidias a declaraciones con flujo complejo
|
|
# por ej. zip(), para el caso anterior:
|
|
list(zip(*matriz)) # ** desempaquetando lista de argumentos
|
|
|
|
print(list(zip(*matriz)))
|
|
# [(1, 5, 9), (2, 6, 10), (3, 7, 11), (4, 8, 12)]
|
|
```
|
|
|
|
|
|
### La instrucción del
|
|
> Elimina uno o mas items de la lista según indice, elimina sección o
|
|
> lista completa, también se usa para eliminar variables.
|
|
```python
|
|
a = [-1, 1, 66.25, 333, 333, 1234.5]
|
|
|
|
del a[0] # quita -1
|
|
del a[2:4] # quita 333 y 333
|
|
del a[:] # vacía la lista
|
|
del a # elimina la variable
|
|
```
|
|
|
|
----
|
|
|
|
## Tuplas
|
|
|
|
Una tupla consiste en valores separados por coma, una tupla va entre parentesis
|
|
```python
|
|
tupla = 12345, 54321, 'hola!'
|
|
tupla[0] #12345
|
|
tupla #(12345, 54321, 'hola!')
|
|
|
|
# las tuplas pueden anidarse
|
|
u = tupla, (1,2,3,4,5,6)
|
|
|
|
# las tuplas son inmutables
|
|
#tupla[0] = 88888
|
|
#TypeError
|
|
# Pero pueden contener objetos mutables
|
|
|
|
# Tuplas con objetos mutables como listas
|
|
|
|
# TUPLAS INMUTABLES
|
|
# LISTAS MUTABLES
|
|
|
|
# Creación de tupas
|
|
vacia = ()
|
|
single = 'hola',
|
|
len(vacia) #0
|
|
len(single) #1
|
|
|
|
# Empaquetado de tupla
|
|
tupla = 1234, 3421, 'hola!'
|
|
|
|
# Tb es posible asignar los elementos a variables
|
|
# Desempaquetado de secuencias
|
|
x, y, z = tupla
|
|
|
|
|
|
# Las tuplas son secuencias ordenadas de valores
|
|
# ejemplos
|
|
|
|
tupla = (1, 2.5, 'Hola')
|
|
|
|
tupla[0] #1
|
|
tupla[1] #2.5
|
|
tupla[2] #'Hola
|
|
|
|
tupla[:2] # (1, 2.5)
|
|
|
|
# Tulpa vacia
|
|
tupla_vacia1 = ()
|
|
tupla_vacia2 = tuple()
|
|
|
|
# Tupla de un elemento
|
|
tupla_2 = (5, )
|
|
# numero_no_tupla = (5)
|
|
|
|
# longitud de tupla
|
|
len(tupla)
|
|
```
|
|
|
|
### Empaquetado y desempaquetado de tuplas
|
|
```python
|
|
# Empaquetado
|
|
a, b, c, = 20, "T", "A"
|
|
tupla = a, b, c
|
|
|
|
# Desempaquetado
|
|
x, y, z = tupla
|
|
```
|
|
|
|
----
|
|
|
|
## Diccionarios
|
|
|
|
Los diccionarios también pueden ser conocidos como "memorias asociativas o "arreglos asociativos".
|
|
|
|
Los diccionarios se indexan con claves, pueden ser cualquiera de tipo inmutable, en vez de
|
|
un rango numérico como en las secuencias.
|
|
|
|
Las tuplas pueden usarse como claves si solamente contienen cadenas, números o
|
|
tuplas; si una tupla contiene cualquier objeto mutable directa o indirectamente,
|
|
no puede usarse como clave.
|
|
Ni tampoco listas, ya que se modifican con **append()** y **extend()**.
|
|
|
|
Los diccionarios se pueden pensar como un conjunto no ridenado de pares **clave: valor**
|
|
siendo las claves **UNICAS**.
|
|
```python
|
|
gente = {} vacia
|
|
gente = {'pepe': 123, 'joel': 234 }
|
|
```
|
|
|
|
### Las operaciones principales son
|
|
- Guardar con una clave
|
|
```python
|
|
gente['raul'] = 345
|
|
```
|
|
- Extraer de un dict. con una clave
|
|
```python
|
|
gente['joel'] # 234
|
|
```
|
|
- Borrar con del clave
|
|
```python
|
|
del gente['pepe']
|
|
```
|
|
- Listar claves
|
|
```python
|
|
list(gente.keys())
|
|
```
|
|
- Ordenar:
|
|
```python
|
|
sorted(gente.keys())
|
|
```
|
|
- condicional busqueda:
|
|
```python
|
|
'joel' in gente #True
|
|
'raul' not in gente #False
|
|
```
|
|
|
|
### Constructor dict()
|
|
**Formas de definir un diccionario**
|
|
```python
|
|
precios = {'manzana': 3.5, 'banana': 4.5, 'kiwi': 6.0, 'pera': 3.75}
|
|
|
|
precios = dict(manzana=3.5, banana=4.5, kiwi=6.0, pera=3.75)
|
|
|
|
precios = dict([('manzana', 3.5), ('banana', 4.5), ('kiwi', 6.0), ('pera', 3.75)])
|
|
```
|
|
|
|
### Acceso a elementos por claves
|
|
```python
|
|
precios['manzana'] # 3.5
|
|
precios['banana'] # 4.5
|
|
precios['kiwi'] # 6.0
|
|
precios['pera'] # 3.75
|
|
#precios['melon'] # KeyError
|
|
|
|
# Agregar un elemento (clave-valor)
|
|
precios['melon'] = 7.5
|
|
|
|
|
|
# Actualizar un elemento (clave-valor)
|
|
precios['manzana'] # 3.0
|
|
|
|
|
|
# Borrar un elemento (clave-valor)
|
|
del precios['kiwi']
|
|
|
|
|
|
# Pertenencia
|
|
'banana' in precios
|
|
'sandia' not in precios
|
|
```
|
|
|
|
### Propio diccionario a partir de 2 listas:
|
|
```python
|
|
pregs = ['nombre','altura','edad']
|
|
resps = ['cilantro', '16', 'a veces']
|
|
|
|
pyr = {}
|
|
for p, r in zip(pregs, resps):
|
|
pyr[p] = r
|
|
|
|
# En una linea
|
|
pyr1 = {p: r for p, r in zip(pregs,resps)}
|
|
|
|
# Mas efectivo
|
|
pyr2 = dict(zip(pregs, resps))
|
|
```
|
|
|
|
### Metodos en los diccionarios
|
|
```python
|
|
precios = {'manzana': 3.5, 'banana': 4.5, 'kiwi': 6.0, 'pera': 3.75}
|
|
|
|
# Cantidad de elementos clave-valor
|
|
len(precios)
|
|
|
|
|
|
# Devuelve el valor de clave indicada, se puede definir una por defecto
|
|
# si no existe, si no se indica None.
|
|
|
|
precios.get('manzana') # 3.5
|
|
precios.get('melon') # None
|
|
precios.get('melon', 0.00) # 0.00
|
|
|
|
|
|
# Si existe devuelve el valor, sino, es creado con el valor default o None
|
|
# en caso de no indicarlo
|
|
|
|
precios.setdefault('banana') #4.5
|
|
precios.setdefault('sandia') #None
|
|
precios.setdefault('pepino', 6.6) #6.6
|
|
|
|
|
|
# Actualizacion de un diccionario
|
|
|
|
precios.update({'banana': 4.0, 'durazno': 5.5})
|
|
precios.update([('durazno', 5.1)])
|
|
|
|
|
|
precios.keys() # Retorna lista con claves del diccionario
|
|
|
|
precios.values() # Retorna lista con los valores del diccionario
|
|
|
|
precios.items() # Retorna lista con los items del diccionario
|
|
|
|
|
|
# Sacar elemento segun clave, se puede definir un default si no lanza KeyError
|
|
|
|
precios.pop('manzana')
|
|
precios.pop('melon', 0.00)
|
|
# precios.pop('melon')
|
|
|
|
|
|
# Sacar elemento segun LIFO (LAST IN FIRST OUT, estilo pila)
|
|
precios.popitem()
|
|
|
|
|
|
# Copia "superficial" de diccionarios
|
|
precios_cp = precios.copy()
|
|
|
|
# Borra los elementos del diccionario
|
|
precios.clear()
|
|
```
|
|
|
|
### Iterando diccionarios
|
|
Vista dinamica de las entradas del diccionario
|
|
```python
|
|
precios = {'manzana': 3.5, 'banana': 4.5, 'kiwi': 6.0, 'pera': 3.75}
|
|
|
|
# Vista de Diccionarios
|
|
claves = precios.keys()
|
|
valores = precios.values()
|
|
items = precios.items()
|
|
|
|
precios['melon'] = 5.5 # Agregado melon al diccionario
|
|
|
|
|
|
# Iteracion de diccionarios
|
|
for fruta, precio in precios.items():
|
|
print("Precio de", fruta, ": $:", precio)
|
|
|
|
# La consulta a las variables previas asignadas como
|
|
# claves, valores e items. Mantienen sus valores actualizados según
|
|
# diccionario (apuntan a la misma direccion de memoria?)
|
|
|
|
print('\n',claves,'\n'*2, valores,'\n'*2, items)
|
|
```
|
|
|
|
> Condiciones que deben cumplir las claves en diccionarios
|
|
>
|
|
> Los diccionarios están implentados internamente como una tabla hash
|
|
> por lo que las claves deben ser objetos **Hasheables**.
|
|
>
|
|
> \*\***hashable** es un obejto que tiene un valor hash
|
|
> que nunca cambia durante el ciclo de vida del programa.
|
|
>
|
|
> Debe tener definido el metodo mágico __HASH__
|
|
> Debe poder ser comparado con otros objetos, es decir
|
|
> Debe tener definido el metodo __EQ__
|
|
> Deben ser iguales cuando su hash son iguales
|
|
>
|
|
> Todos los objetos inmutables ofrecidos Built-In en Python son hasheables.
|
|
> Ej,: **strings - numeros - tuplas - fechas**
|
|
>
|
|
> Los contenedores mutables como las listas, conjuntos,
|
|
> los diccionarios **no** son hasheables.
|
|
>
|
|
> Los objetos que son definidos por instancias de clases definidas por el
|
|
> usuario **son** hasheables por defecto.
|
|
>
|
|
> Los hash al compararse, siempre son distintos a otros obejos,
|
|
> salvo a si mismos.
|
|
>
|
|
> Su valor hash se deriba de su ID que es único
|
|
|
|
|
|
### Resumen diccionarios
|
|
```python
|
|
dict([('pepe', 1234), ('joel', 2345), ('raul', 3456)])
|
|
|
|
# Creación por comprensión de diccionarios desde expresiones arbitrarias clave/valor
|
|
otro = {x: x ** 2 for x in (2, 4, 6)}
|
|
# {2: 4, 4: 16, 6: 36}
|
|
|
|
# Si las claves son cadenas simples, se pueden especificar usando argumentos por claves****
|
|
otro = dict(pepe=1234, joel=2345, raul=3456)
|
|
# {'pepe': 1234, 'joel': 2345, 'raul': 3456}
|
|
|
|
# ITERACION .items()
|
|
caballeros = {'seya': 'pegaso', 'yoga': 'cisne'}
|
|
|
|
for k, v in caballeros.items():
|
|
print(k, v)
|
|
|
|
# Al iterar una secuencia se puede obtener tanto el índice como el valor correspondiente,
|
|
# usando la finción "enumerate()"
|
|
|
|
for k, v in enumerate(caballeros):
|
|
print(k, v)
|
|
|
|
# 0 seya
|
|
# 1 yoga
|
|
|
|
|
|
# Iterar sobre 2 o mas secuencias, emparejando valores con "zip()"
|
|
|
|
pregs = ['nombre', 'objetivo', 'color favorito']
|
|
resps = ['Yorldan', 'volar', 'diciembre']
|
|
|
|
for p, r in zip(pregs, resps):
|
|
print('Cual es tu {0}? {1}.'.format(p, r))
|
|
|
|
# Iterar en orden inverso
|
|
|
|
for i in reversed(range(1, 10, 2)):
|
|
print(i)
|
|
|
|
# Iterar secuencia ordenada "sorted()"
|
|
# sorted devuelve una nueva lista ordenada
|
|
# recordatorio set() <--- conjunto
|
|
canasta = ['manzana', 'naranja', 'manzana', 'pera', 'naranaja', 'banana']
|
|
for f in sorted(set(canasta)):
|
|
print(f)
|
|
|
|
# A veces, es mas simple y seguro crear una nueva lista,
|
|
# en vez de cambiar una lista mientras se recorre.
|
|
import math
|
|
|
|
datos = [56.2, float('NaN'), 51.7, 55.3, 52.5, float('NaN'), 47.8]
|
|
datos_filtrados = []
|
|
for valor in datos:
|
|
if not math.isnan(valor):
|
|
datos_filtrados.append(valor)
|
|
|
|
# datos_filtrados ---> [56.2, 51.7, 55.3, 52.5, 47.8]
|
|
|
|
|
|
# Recopilacion de metodos de mas arriba
|
|
# gente['raul'] = 345
|
|
# otro = dict(pepe=1234, joel=2345, raul=3456)
|
|
# otro = { x: x ** 2 for x in (2, 4, 6) }
|
|
|
|
|
|
# Base para crear Diccionarios con dos listas
|
|
pyr = {}
|
|
for p, r in zip(pregs, resps):
|
|
pyr[p] = r
|
|
|
|
pyr1 = {p: r for p, r in zip(pregs, resps)}
|
|
|
|
pyr2 = dict(zip(pregs, resps))
|
|
```
|
|
|
|
----
|
|
|
|
|
|
## Generadores
|
|
|
|
Son funciones especiales, devuelven una secuencia de valores, de uno en uno,
|
|
en cada llamada. Son una forma sencilla y potente de iterador.
|
|
|
|
Un iterador tiene siempre sus elementos disponibles, un generador los va
|
|
**generando** con un llamado al metodo **__next()__**
|
|
|
|
Con esto se pueden tener generadores, que generen infitinos elementos,
|
|
*ej. nums. naturales.*
|
|
|
|
Retornan un resultado con la sentencia **yield**.
|
|
La función queda en "**pausa**" hasta que es invocada nuevamente.
|
|
|
|
|
|
### Creación de generador
|
|
Un grador. de nros. 0-9
|
|
```python
|
|
def gen_10():
|
|
for n in range(10):
|
|
yield n
|
|
```
|
|
|
|
Uso, hay que instanciar el generador. Luego usar la funcion **__next__()**
|
|
al no quedar elementos que iterar, el generador lanza una excepción **StopIteration**
|
|
```python
|
|
a_gen_10 = gen_10() # Instancia del generador
|
|
|
|
a_gen_10.__next__() # 0
|
|
a_gen_10.__next__() # 1
|
|
a_gen_10.__next__() # 2
|
|
... # 3..8
|
|
a_gen_10.__next__() # 9
|
|
a_gen_10.__next__() # Traceback (most recent call last):
|
|
# File "<stdin>", line 1, in <module>
|
|
# StopIteration
|
|
```
|
|
|
|
Al igual que los iteradores, los generadores se pueden "consumir" con un ciclo for.
|
|
**ej. Generador nros. naturales, infinitos**
|
|
```python
|
|
def naturales():
|
|
n = 1
|
|
while True:
|
|
yield n
|
|
n += 1
|
|
|
|
nats = naturales()
|
|
```
|
|
|
|
**ej. Sentencia "return" para indicar StopIteration**
|
|
```python
|
|
def n_nats(n):
|
|
i = 1
|
|
while True:
|
|
if i > n:
|
|
return
|
|
yield i
|
|
i += 1
|
|
```
|
|
|
|
### Generar los 100 primeros números naturales
|
|
Similar a las listas por comprensión, solo que estas se escriben entre parentesis
|
|
```python
|
|
# Lista por Comprensión
|
|
[p for p in range(10) if p % 2 == 0]
|
|
# [0, 2, 4, 6, 8]
|
|
|
|
# Generador
|
|
(p for p in range(10) if p % 2 == 0)
|
|
# <generator object <genexpr> at 0x7fb25c49da50>
|
|
```
|
|
|
|
> Los generadores son útiles:
|
|
> - Trabajando con estructuras infinitas.
|
|
> - Trabajando con estructuras con alta carga de memoria, se puede reducir el espacio a revisar.
|
|
> - Se puede retrasar su calculo hasta último momento para favorecer otros procesos.
|
|
> - Se puede pasar un argumento en caso de acabar el generador.
|
|
> ejemplo: `next(nats, None)`, `next(nats, 'ratas')`
|
|
|
|
### Envio de objetos a un generador con send()
|
|
Esto también produce la 'generación'
|
|
```python
|
|
def accumulator():
|
|
total = 0
|
|
value = None
|
|
while True:
|
|
# receive sent value
|
|
value = yield total
|
|
if value is None:
|
|
break
|
|
# aggregate values
|
|
total += value
|
|
|
|
generator = accumulator()
|
|
# advance until the first "yield"
|
|
next(generator) # 0
|
|
# from this point on, the generator aggregates values
|
|
generator.send(1) # 1
|
|
generator.send(10) # 11
|
|
generator.send(100) # 111
|
|
|
|
# Calling next(generator) is equivalent to calling generator.send(None)
|
|
# next(generator) # StopIteration
|
|
```
|
|
|
|
### Uso de generadores
|
|
```python
|
|
def gen1000():
|
|
"Genera los pri meros 1000 números."
|
|
|
|
for x in range(1000):
|
|
yield x
|
|
|
|
|
|
primeros1000 = gen1000()
|
|
|
|
for x in primeros1000:
|
|
print(x, end=" - ")
|
|
|
|
|
|
print('\n'*2)
|
|
```
|
|
```python
|
|
def gen_primos(cantidad=1):
|
|
"Generador de números primos."
|
|
|
|
cont = 1
|
|
ls_prim = []
|
|
|
|
# Comienzo ciclo infinito
|
|
while cantidad > cont:
|
|
es_primo = True
|
|
cont += 1
|
|
if len(ls_prim) > 0:
|
|
for primo in ls_prim:
|
|
if cont % primo == 0:
|
|
es_primo = False
|
|
break
|
|
if es_primo:
|
|
ls_prim.append(cont)
|
|
yield cont
|
|
|
|
prim1000prim = gen_primos(1000)
|
|
|
|
for x in prim1000prim:
|
|
print(x, end=" - ")
|
|
```
|
|
```python
|
|
def num_par(n):
|
|
return (x for x in range(n) if x % 2 == 0)
|
|
|
|
gen = num_par(15)
|
|
|
|
gen.__next__()
|
|
gen.__next__()
|
|
print(list(gen))
|
|
```
|
|
|
|
----
|
|
|
|
## Decoradores
|
|
|
|
Los decoradores son funciones, que toman por argumento una función,
|
|
y devuelven otra funcion.
|
|
- Ayudan a hacer codigo mas limpio
|
|
- Reducen el codigo común y repetitivo
|
|
- Favorecen la separacion de responsabilidades del codigo
|
|
- Aumentan la legibilidad y mantenibilidad del progama
|
|
|
|
Son funciones:
|
|
- Reciben una funcion y devuelven otra función.
|
|
- Sirven para extender funcionalidad de una func.
|
|
o también para agregar funcionalidad yuxtapuesta a la misma.
|
|
|
|
ej. Decorando una función, con otra que mide el tiempo de ejecución
|
|
|
|
> Notar el orden:
|
|
> explicit args, luego \*args, luego \*\*kwargs.
|
|
> ejm. `def foo(arg1, arg2, *args, **kwargs):`
|
|
|
|
```python
|
|
def smart_division(div_func):
|
|
def div(a, b):
|
|
if b == 0:
|
|
print("No se puede dividir por cero!")
|
|
return
|
|
return div_func(a, b)
|
|
return div
|
|
|
|
@smart_division
|
|
def division(a, b):
|
|
return a / b
|
|
|
|
r = division(1, 2)
|
|
print(r)
|
|
|
|
r = division(2, 0)
|
|
print(r)
|
|
```
|
|
|
|
### Decorador generico
|
|
El anterior recibe 2 parametros en este vamos a pasar cualquier cantidad de argumentos
|
|
```python
|
|
def log(f):
|
|
def wrap(*args, **kwargs):
|
|
print('Ejecutando la función', f.__name__,
|
|
'con los argumentos', ', '.join([str(arg) for arg in args]))
|
|
return f(*args, **kwargs)
|
|
return wrap
|
|
|
|
@log
|
|
def suma(a, b):
|
|
return a + b
|
|
|
|
print(suma(1,2), '\n')
|
|
|
|
@log
|
|
@smart_division
|
|
def division_2(a, b):
|
|
return a / b
|
|
|
|
r = division_2(1, 2)
|
|
print(r)
|
|
|
|
r = division_2(2, 0)
|
|
print(r)
|
|
```
|
|
|
|
Los decoradores sirven para un código mas legible y cohesionado.
|
|
|
|
|
|
### Mas decoradores
|
|
```python
|
|
import time
|
|
|
|
def time_meter(f):
|
|
def wrap(*args, **kwargs):
|
|
ti = time.time()
|
|
result = f(*args, **kwargs)
|
|
tf = time.time()
|
|
etime = tf-ti
|
|
print("La func.",f.__name__,"demoró",round(etime, 5),"segundos en ejecutarse")
|
|
return result
|
|
return wrap
|
|
|
|
|
|
@time_meter
|
|
def suma(a, b):
|
|
time.sleep(0.2)
|
|
print('retraso')
|
|
return a+b
|
|
|
|
suma(1,3)
|
|
```
|
|
|
|
|
|
### Los decoradores tb pueden recibir parametros
|
|
```python
|
|
def logger(debug=False):
|
|
def _logger(func):
|
|
def inner(*args,**kwargs):
|
|
if debug:
|
|
print("Modo Debug")
|
|
for i, arg in enumerate(args):
|
|
print("arg %d:%s" % (i,arg))
|
|
return func(*args, *kwargs)
|
|
return inner
|
|
return _logger
|
|
|
|
|
|
@logger(True)
|
|
def suma(a,b):
|
|
return a+b
|
|
|
|
suma(2, 5)
|
|
|
|
#Modo debug
|
|
#arg 0:2
|
|
#arg 1:57
|
|
#7
|
|
|
|
@logger(False)
|
|
def suma(a, b):
|
|
return a + b
|
|
|
|
suma(2, 5)
|
|
|
|
#arg 0:2
|
|
#arg 1:57
|
|
#7
|
|
|
|
# Este tieme una función anidada más, el decorador recibe parámetros propios
|
|
# La 1ra función anidada recibe la función decorada.
|
|
# La 3ra función anidada tiene la lógica del decorador.
|
|
|
|
# Los decoradores pueden anidarse, una funcion puede tener muchos decoradores
|
|
# ej.
|
|
|
|
@logger(True)
|
|
@time_meter
|
|
def suma(a,b):
|
|
return a+b
|
|
|
|
suma(2, 7)
|
|
|
|
print('')
|
|
|
|
@time_meter
|
|
@logger(True)
|
|
def suma(a,b):
|
|
return a+b
|
|
|
|
suma(2, 7)
|
|
```
|
|
|
|
----
|
|
|
|
## Ejercicios Modulo 2
|
|
|
|
### Verdureria
|
|
```python
|
|
La verdulería greengrocer nos pasó su listado de precios por kilo.
|
|
Utilizando una consola de Python, crear el diccionario con la lista de precios:
|
|
precios = {'manzana': 3.5,
|
|
'banana': 4.5,
|
|
'kiwi': 6.0,
|
|
'pera': 3.75,
|
|
'ciruela': 2.45,
|
|
'durazno': 4.55,
|
|
'melon': 7.35,
|
|
'sandia': 9.70,
|
|
'anana': 11.25}
|
|
```
|
|
|
|
Si tenemos el siguiente ticket de una compra
|
|
```
|
|
2 kg de manzana
|
|
2.5 kg de banana
|
|
1 kg de kiwi
|
|
3 kg de pera
|
|
1 kg de ciruela
|
|
2 kg de durazno
|
|
5 kg de melón
|
|
10 kg de sandía
|
|
3 kg de ananá
|
|
```
|
|
|
|
¿Cuál es el precio del ticket de compra?
|
|
```python
|
|
precios = {
|
|
'manzana' : 3.5,
|
|
'banana' : 4.5,
|
|
'kiwi' : 6.0,
|
|
'pera' : 3.75,
|
|
'ciruela' : 2.45,
|
|
'durazno' : 4.55,
|
|
'melon' : 7.35,
|
|
'sandia' : 9.70,
|
|
'anana' : 11.25,
|
|
}
|
|
|
|
pedido = {
|
|
'manzana' : 2.0,
|
|
'banana' : 2.5,
|
|
'kiwi' : 1.0,
|
|
'pera' : 3.0,
|
|
'ciruela' : 1.0,
|
|
'durazno' : 2.0,
|
|
'melon' : 5.0,
|
|
'sandia' : 10.0,
|
|
'anana' : 3.0,
|
|
}
|
|
|
|
|
|
|
|
sub_total = 0
|
|
for key in pedido.keys():
|
|
if key in precios.keys():
|
|
sub_total += pedido[key] * precios[key]
|
|
|
|
print('TOTAL =', sub_total)
|
|
|
|
d = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
|
|
|
|
resp = d.get('z', 7) == 7
|
|
print(resp)
|
|
|
|
resp = d.get('z') == None
|
|
print(resp)
|
|
|
|
resp = d.setdefault('z', 5) == 5
|
|
print(resp)
|
|
|
|
resp = d.setdefault('a', 7) == 7
|
|
print(resp)
|
|
|
|
resp = d['a'] == 1
|
|
print(resp)
|
|
|
|
resp = d.get('a', 3) == 3
|
|
print(resp)
|
|
|
|
|
|
d.update([('a', 10)])
|
|
print(d.get('a'))
|
|
|
|
d.update({'a': 1, 'b': 3})
|
|
print(d.get('a'), d.get('b'))
|
|
|
|
d.update((('a', 45), ('b', 54)))
|
|
print(d.get('a'), d.get('b'))
|
|
|
|
|
|
d = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
|
|
|
|
resp = d.pop('f', 2) == 2
|
|
print(resp)
|
|
print(d)
|
|
|
|
resp = d.pop('c') == 3
|
|
print(resp)
|
|
|
|
d = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
|
|
resp = d.popitem() == 5
|
|
print(resp)
|
|
|
|
|
|
d = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
|
|
resp = d.pop('a', 2) == 2
|
|
print(resp)
|
|
|
|
#d = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
|
|
#resp = d.popitem() == (e, 5)
|
|
#print(resp)
|
|
|
|
d = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
|
|
resp = d.pop() == 5
|
|
print(resp)
|
|
|
|
espera = input('esperando')
|
|
print(espera)
|
|
```
|
|
|
|
----
|
|
|
|
## El Gato
|
|
```
|
|
Deberás programar el juego TA-TE-TI.
|
|
Cuando el programa comienza a correr, en la pantalla aparece el tablero de TA-TE-TI (de 3x3)
|
|
y un input que permite al usuario elegir el símbolo “X” o el símbolo “O”. Las “X” empiezan.
|
|
|
|
El usuario debe elegir la posición del tablero (esta posición debe ser correcta y no debe
|
|
estar ocupada) donde poner el símbolo en el tablero y el sistema valida si el juego termina
|
|
con un ganador o en empate.
|
|
|
|
Si no hay ganador o la partida no terminó todavía en empate, el juego continúa preguntando
|
|
al otro usuario que seleccione la posición del tablero dónde quiere poner su símbolo y así
|
|
siguiendo hasta que la partida termine con un ganador o en empate.
|
|
|
|
Notas:
|
|
Representar el tablero como una matriz de 3x3.
|
|
El juego termina en empate cuando el tablero está completo y no hay ganadores.
|
|
```
|
|
|
|
> Este archivo ha sido creado con fines didacticos y como entrega final del 2do
|
|
> modulo del Curso Aprende a Programar en Python, dictado por la Universidad Austral,
|
|
> a travez de Coursera
|
|
> @autor: devfzn@gmail.com
|
|
|
|
```python
|
|
import random
|
|
import os
|
|
from time import sleep
|
|
|
|
clear = lambda: os.system('clear') if os.name == 'posix' else os.system('cls')
|
|
limpiar_pantalla = True
|
|
|
|
""" Creación de matriz base"""
|
|
#matriz = [['a1', 'b1', 'c1'], ['a2', 'b2', 'c2'], ['a3', 'b3', 'c3']]
|
|
matriz = [['|_','|_','|_'], ['|_','|_','|_'], ['|_','|_','|_']]
|
|
# Creacción de dicionario vacío y lista de llaves.
|
|
master, llaves = {}, [x+y for x in 'abc' for y in '123']
|
|
|
|
# Preguntas para solicitar entradas de usuario
|
|
lado = '\tEscribe \'o\' para jugar con \'O\',\n\to \'x\' para jugar con \'X\',\n\t(\'X\' hace la primera jugada)\n\t> '
|
|
salir = '\tJugar Otra? (si/no)\n\t> '
|
|
jugada = '\tIngresa tu jugada (ej. a2)\n\t> '
|
|
tit_V = 'Ganaste, Felicitaciones!'
|
|
tit_P = ' Has perdido'
|
|
|
|
# Lista con tuplas de condiciones para ganar o perder el juego.
|
|
ganadoras = [('a1', 'b1', 'c1'),
|
|
('a2', 'b2', 'c2'),
|
|
('a3', 'b3', 'c3'),
|
|
('a1', 'a2', 'a3'),
|
|
('b1', 'b2', 'b3'),
|
|
('c1', 'c2', 'c3'),
|
|
('a1', 'b2', 'c3'),
|
|
('c1', 'b2', 'a3')]
|
|
|
|
def actualizar_matriz():
|
|
"""
|
|
Actualiza los valores en la matriz según los valores en diccionario maestro
|
|
:return: None
|
|
"""
|
|
x, y = 0, 0 # Variables para indices de matriz tablero
|
|
for valor in master.values(): # Recorre los valores del diccionario
|
|
if not y < 3: # Limite indice columnas
|
|
y = 0 # Reinicio contador columnas
|
|
x += 1 # Autoincremento de fila al llegar a 3ra columna
|
|
matriz[y][x] = valor # Asigna el valor del diccionario a la matriz (casilla)
|
|
y += 1 # Autoincremento de columna
|
|
|
|
def dibujar_tablero(*frase):
|
|
"""
|
|
Muestra en pantalla un string pasado como argumento,
|
|
(coordenadas y matriz de juego)
|
|
:param frase: titulo a mostrar según circunstancia
|
|
:return: None
|
|
"""
|
|
if limpiar_pantalla:
|
|
clear()
|
|
print('\n\t', *frase, '\n\n\t\t a b c')
|
|
for x in range(len(matriz)):
|
|
print('\t\t', end=str(x+1))
|
|
for y in range(len(matriz[x])):
|
|
print(matriz[x][y], end='')
|
|
print('|')
|
|
print('\n')
|
|
|
|
|
|
# ANIMACION
|
|
saludo = ['\n\tBienvenido al Clasico ', '\n\n\n\t\t\"GATO!\"']
|
|
jugadas = [[0, 0], [1, 2], [2, 0], [1, 0], [1, 1], [2, 2], [0, 2]]
|
|
|
|
def parp_text(repets, *texto):
|
|
print(len(texto))
|
|
x, sec = 0, True
|
|
while x < repets:
|
|
for txt in texto:
|
|
for tx in txt:
|
|
clear()
|
|
print('\n\t', tx)
|
|
sleep(0.7)
|
|
x += 1
|
|
sleep(1)
|
|
|
|
def animacion():
|
|
actualizar_matriz()
|
|
for x in range(len(jugadas)):
|
|
if x % 2 == 0:
|
|
matriz[jugadas[x][0]][jugadas[x][1]] = '|X'
|
|
else:
|
|
matriz[jugadas[x][0]][jugadas[x][1]] = '|O'
|
|
dibujar_tablero('\"devfzn@gmail.com\"')
|
|
sleep(0.5)
|
|
|
|
|
|
animacion()
|
|
parp_text(2, saludo)
|
|
|
|
|
|
def input_usr(pregunta, respuestas):
|
|
"""
|
|
Solicita una entrada al usuario, recive 1 string y una lista de string
|
|
:param pregunta: string Pregunta a realizar
|
|
:param respuestas: [string] Lista de posibles respuestas en mayúscula
|
|
:return: 'string' input de usuario validado
|
|
"""
|
|
resp = '' # Variable que recibe entrada de usuario
|
|
while resp not in respuestas: # Valida respuesta según 'respuestas'
|
|
resp = input(pregunta).upper() # Asignación entrada de usuario (mayusculas forzadas)
|
|
return resp
|
|
|
|
|
|
jugar = True # Variable que gobierna el ciclo principal (Juego)
|
|
while jugar: # Ciclo principal
|
|
global turno #
|
|
for llave in llaves: # Recorre las llaves y asgina '|_'(vacío) a cada item
|
|
master[llave] = '|_'
|
|
slave = master.copy() # Copia superficial del diccionario maestro
|
|
actualizar_matriz() # Poblar matríz con los valores del diccionario maestro
|
|
dibujar_tablero(' Elige el lado X - O') # Imprime matríz en pantalla
|
|
global p1
|
|
p1 = input_usr(lado, ['x', 'X', 'o', 'O']) # Asignación de entrada de usuario, P1 (Player 1)
|
|
titulo = 'P1 jugando con -> ' + p1
|
|
cambio = lambda x: 'O' if x == 'X' else 'X' # Función anónima retorna el símbolo opuesto al evaluado X,O
|
|
global pc
|
|
pc = cambio(p1) # Asignación de símbolo a jugador PC (Player Computer)
|
|
turno = 0 # Contador de turnos jugados
|
|
|
|
dibujar_tablero(titulo)
|
|
|
|
def turno_p1():
|
|
"""
|
|
Función que recibe una entrada de usuario y la valida
|
|
según la copia de las llaves del diccionario maestro.
|
|
Actualiza el valor en el diccionario maestro con el
|
|
symbolo seleccionado por el jugador PC y e xtrae la copia de 'slave'
|
|
:return: None
|
|
"""
|
|
jp1 = input_usr(jugada, list(x.upper() for x in list(slave.keys()))).lower()
|
|
slave.pop(jp1)
|
|
master[jp1] = '|' + p1
|
|
|
|
|
|
def turno_pc():
|
|
"""
|
|
Función que selecciona una llave al azar de la copia del
|
|
diccionario maestro y actualiza a este último con el simbolo
|
|
del jugador PC.
|
|
Despues del turo nro. 2 evalúa si hay algún espacio estrategico,
|
|
donde existen dos simbolos iguales, pone el tercero, priorizando
|
|
los pares de symbolos afines con el bando asignado.
|
|
:return: None
|
|
"""
|
|
if turno > 2:
|
|
falta, hay_par = (), False
|
|
for pos in ganadoras:
|
|
a, b, c = master[pos[0]], master[pos[1]], master[pos[2]]
|
|
if '|_' != a == b != c == '|_':
|
|
falta = (a, pos[2])
|
|
hay_par = True
|
|
if a == pc + '|_':
|
|
break
|
|
elif '|_' != a == c != b == '|_':
|
|
falta = (a, pos[1])
|
|
hay_par = True
|
|
if a == pc + '|_':
|
|
break
|
|
elif '|_' != c == b != a == '|_':
|
|
falta = (c, pos[0])
|
|
hay_par = True
|
|
if c == pc + '|_':
|
|
break
|
|
if hay_par:
|
|
jpc = falta[1]
|
|
else:
|
|
jpc = ''.join(random.choice(list(slave.keys())))
|
|
else:
|
|
jpc = ''.join(random.choice(list(slave.keys())))
|
|
slave.pop(jpc)
|
|
master[jpc] = '|' + pc
|
|
|
|
|
|
def eval_term():
|
|
"""
|
|
Función que evalua si se cumplen las condiciones para terminar la partida.
|
|
Compara los valores el diccionario 'maestro' según las llaves en las tuplas,
|
|
de la lista 'ganadaoras'. Asigna un titulo y un valor al booleano 'termino'
|
|
:return: None
|
|
"""
|
|
global titulo
|
|
global termino
|
|
for g in ganadoras:
|
|
test = master[g[0]]
|
|
test2 = '|' + p1
|
|
if '|_' != test == master[g[1]] == master[g[2]]:
|
|
termino = True
|
|
titulo = tit_V if test2 == '|X' == test else tit_V if test2 == '|O' == test else tit_P
|
|
if turno > 8 and not termino:
|
|
termino, titulo = True, '\t EMPATE'
|
|
|
|
|
|
X = p1 == 'X' # Booleano indica si jugador 1 es 'X'
|
|
termino = False # Booleano que gobierna ciclo de jugadas
|
|
while not termino: # Ciclo de jugadas
|
|
turno_p1() if X else turno_pc() # Alterna el turno del Player1 y PC, segun 'X'
|
|
X = not X # Alterna el booleano 'X'
|
|
turno += 1
|
|
eval_term()
|
|
actualizar_matriz()
|
|
dibujar_tablero(titulo)
|
|
|
|
resp = input_usr(salir, ['N', 'NO', 'S', 'SI'])
|
|
jugar = resp in 'SI' # Actualización del booleano que gobierna while principal
|
|
|
|
autor = ['', '\n\n\t "devfzn@gmail.com\"']
|
|
parp_text(4, autor)
|
|
```
|
|
|