variable_1 = 1
variable_2 = 'Hello, world!'
variable_3 = True

"""
Explanation: How to Python -- An introduction to variables
Resumen rapido de python -- lo mas basico:
Python es un lenguaje de programacion de alto nivel orientado a objetos (OOP).
Que puede hacer python?

Se puede usar en servidores para crear aplicaciones
Se puede usar para conectar sistemas de bases de datos
Es muy util para crear prototipos rapidos
Es capaz de manejar grandes volumenes de datos
Es capaz de llevar a cabo matematica compleja, y por lo tanto es tremendamente util para hacer ciencia

Por que usar python?

Python funciona en casi todas las plataformas (Windows, OS X, Linux, etc)
Python tiene una sintaxis increiblemente sencilla sin necesidad de declarar tipos ni de terminar lineas con ;
Python es un lenguaje interpretado, por lo tanto no es necesario compilar programas para correrlos
A pesar de ser un lenguaje OOP, se puede utilizar como lenguaje funcional o como un lenguaje de procedimientos (procedural languaje)

Basic of Python
Variables

Una variable es un espacio de memoria en el computador que guarda un dato

Tipos de variables:

Numericas (int, float, complex), texto (str), boolean (bool)
Los int, float o complex pueden ser cualquier numero, la diferencia es que los int son numeros enteros y los float no necesariamente
Los string pueden ser cualquier cadena de texto, siempre encerrada entre comillas simples o dobles
Los bool son True o False

Como se escriben?
Las variables llevan un nombre y un valor, este valor se asigna con el signo =
Ejemplos
End of explanation
"""


print(2 + 2)
print(2 - 2)
print(2 * 2)
print(2 / 2)

"""
Explanation: A diferencia de otros lenguajes, no hubo que especificar que tipo de variable seria cada una. El interprete lo hace automaticamente.
Nombres de variables:

El nombre de una variable debe empezar con una letra o con un guion bajo (_), pero NUNCA con un numero
El nombre de una variable solo puede contener caracteres alfa-numericos o guiones bajos
Los nombres de variables reconocen mayusculas (hola != HoLa)

Operadores
Para realizar calculos matematicos complejos primero se debe poder realizar calculos simples
- suma ( + ), resta ( - ), multiplicacion ( * ), division ( / )
Ejemplos
End of explanation
"""


print(2 ** 3)
print(3 // 2)
print(6 % 3)

"""
Explanation: Tambien se pueden realizar operaciones mas complejas como potencia ( ** ), division entera ( // ) y modulo ( % )
Ejemplos
End of explanation
"""


print(True and False)
print(True and True)
print(True or False)
print(False or False)
print(not True)
print(not False)

"""
Explanation: Operadores booleanos:

and : retorna True si se comparan dos booleanos True
or : retorna True si al menos uno de los booleanos comparados es True
not : invierte el booleano
== : retorna True si dos objetos son iguales
!= : retorna True si dos objetos no son iguales
a < b : retorna True si a es menor que b
a <= b : retorna True si a es menor o igual que b
a > b : retorna True si a es mayor que b
a >= b : retorna True si a es mayor o igual que b

Ejemplos:
End of explanation
"""


print('10 en binario: {0:b}'.format(10))
print(' 5 en binario: 0{0:b}'.format(5))
print('10 & 5 en binario: {0:b}'.format(10 & 5), end='\n\n')

print('10 en binario: {0:b}'.format(10))
print(' 5 en binario: 0{0:b}'.format(5))
print('10 | 5 en binario: {0:b}'.format(10 | 5), end='\n\n')

print('10 en binario: {0:b}'.format(10))
print(' 7 en binario: 0{0:b}'.format(7))
print('10 ^ 7 en binario: {0:b}'.format(10 ^ 7), end='\n\n')

print('13 en binario: {0:b}'.format(13))
print('~13 en binario: {0:b}'.format(~13), end='\n\n')

print('10 en binario: {0:b}'.format(10))
print('10 >> 1 en binario: {0:b}'.format(10 >> 1), end='\n\n')

print('10 en binario: {0:b}'.format(10))
print('10 << 1 en binario: {0:b}'.format(10 << 1), end='\n\n')

"""
Explanation: Operadores de identidad:

is : retorna True si ambas variables son el mismo objeto
is not : retorna False si las variables no son el mismo objeto

Operadores de pertenencia:

in : Retorna True si una secuencia esta presente en un objeto
not in : Retorna True si una secuencia no esta presente en un objeto

Operaciones a nivel de bits:

& bitwise AND
| bitwise OR
^ bitwise XOR
~ NOT
<< left shift
>> right shift

Ejemplos:
End of explanation
"""


x = 5
print(x)
x += 1
print(x)
x -= 3
print(x)
x *= 2
print(x)
x /= 3
print(x)
x **= 3
print(x)

"""
Explanation: Operadores de asignacion
Los operadores de asignacion se utilizan para asignar valores a las variables, estos son:
- Ya vimos el operador = que simplemente asigna un valor a una variable
- += toma la variable, le suma otra y reasigna el resultado a la variable original
- -= toma la variable, le resta otra y reasigna el resultado a la variable original
- *= toma la variable, la multiplica por otra y reasigna el resultado a la variable original
- /= toma la variable, la divide por otra y reasigna el resultado a la variable original
- %= toma la variable, le toma el modulo de otra y reasigna el resultado a la variable original
- **= toma la variable, la eleva a otra y reasigna el resultado a la variable original
- &= toma la variable, le aplica bitwise AND y reasigna el resultado a la variable original
- |= toma la variable, le aplica bitwise OR y reasigna el resultado a la variable original
- ^= toma la variable, le aplica bitwise XOR y reasigna el resultado a la variable original
- >>= toma la variable, le aplica un shift a los bits hacia la derecha y reasigna el resultado a la variable original
- <<= toma la variable, le aplica un shift a los bits hacia la izquierda y reasigna el resultado a la variable original
Ejemplos:
End of explanation
"""


l = list([1, 2, 3])
t = tuple((4, 5))
s = set({6, 7, 8})
d = dict({'a': 1})
print(l)
print(t)
print(s)
print(d)

"""
Explanation: Colecciones:
Las colecciones son objetos que representan un conjunto de objetos. Hay 4 objetos de este tipo nativos de python:
- Listas : Colecciones cuyos elementos estan ordenados y son intercambiables. Se permiten elementos duplicados
- Tuplas : Colecciones cuyos elementos estan ordenados y no son intercambiables. Se permiten elementos duplicados
- Set : Colecciones cuyos elementos no estan ordenados y no estan indexados. No se permiten elementos duplicados
- Diccionarios : Colecciones cuyos elementos no estan ordenados, son intercambiables y estan indexados. No se permiten elementos duplicados
Ejemplos:
End of explanation
"""


l = list([1, 2, 3])
print(l[0])
print(l[-1])
t = tuple((4, 5, 6))
print(t[1])
print(t[-2])
d = dict({'llave1': 7, 'llave2': 8})
print(d['llave1'])
print(d['llave2'])

"""
Explanation: Los mas usados son las listas, tuplas y diccionarios asi que veremos operaciones basicas con ellos
Acceder a elementos:
Para acceder a elementos de una coleccion se utilizan los parentesis cuadrados con el indice en su interior (por ejemplo, l[3])
- En el caso de las listas y tuplas, los elementos estan indexados numericamentes tal que el primer elemento es el numero 0
- Tambien se puede acceder a los elementos usando numeros negativos. En este caso, el ultimo elemento es el numero -1
- Los diccionarios tienen una indexizacion personalizada. Al crear uno se hace dict({llave: valor})
End of explanation
"""


l = list([1, 2, 4])
print(l[-1])
l[-1] = 3
print(l[-1])
d = dict({'llave1': 5})
print(d['llave1'])
d['llave1'] = 4
print(d['llave1'])

"""
Explanation: Modificacion de elementos:
(recuerden que las tuplas no son modificables!)
End of explanation
"""


l = list(['a', 'b', 'c'])
print('a' in l)
d = dict({'1': 'a', '2': 'b', '3': 'c'})
print('b' in d)
print('3' in d)

"""
Explanation: Podemos revisar si un elemento existe dentro de una coleccion:
End of explanation
"""


l = list([1, 2, 3, 4, 5, 6, 7])
print(len(l))
d = dict({'a': 1, 'b': 2})
print(len(d))

"""
Explanation: En el caso de los diccionarios, el operador in solo busca si un elemento existe dentro de las llaves del diccionario, y no dentro de los valores!!
Podemos encontrar el largo de una coleccion facilmente
End of explanation
"""


l = list([1, 2, 3, 4])
print(l)
l.append(5)
print(l)
l.remove(2)
l.pop()
print(l)
print(l)
d = dict({'a': 1})
print(d)
d['b'] = 2
print(d)
del d['b']
print(d)

"""
Explanation: Podemos agregar y quitar elementos
End of explanation
"""


l = ['a', 'b', 'c']
t = (1, 2, 3)
d = {'a': 1, 'b': 2, 'c': 3}
print(l)
print(t)
print(d)

"""
Explanation: Hasta ahora las listas, tuplas y diccionarios se han creado usando list(), tuple(), y dict() respectivamente, sin embargo se pueden crear sin usaar estas instrucciones:
End of explanation
"""


