Clase 1: Introducción al lenguaje

Cómo empezar: Instalación y uso

Python es un lenguaje de programación interpretado, que se puede ejecutar sobre distintos sistemas operativos, esto se conoce como multiplataforma (suele usarse el término cross-platform). Además, la mayoría de los programas que existen (y posiblemente todos los que nosotros escribamos) pueden ejecutarse tanto en Linux como en windows y en Mac sin realizar ningún cambio.

Nota

Hay dos versiones activas del lenguaje Python.

  • Python2.X (Python 2) es una versión madura, estable, y con muchas aplicaciones, y utilidades disponibles. No se desarrolla pero se corrigen los errores. Su uso ha disminuido mucho en los últimos años y esencialmente todo el ecosistema de bibliotecas se ha convertido a Python-3

  • Python3.X (Python 3) es la versión actual. Se introdujo por primera vez en 2008, y produjo cambios incompatibles con Python 2. Por esa razón se mantienen ambas versiones y algunos de los desarrollos de Python 3 se portan a Python 2. En este momento la gran mayoría de las utilidades de Python 2 han sido modificadas para Python 3 por lo que, salvo muy contadas excepciones, no hay razones para seguir utilizando Python 2 en aplicaciones nuevas.

Instalación

En este curso utilizaremos Python 3

Para una instalación fácil de Python y los paquetes para uso científico se pueden usar alguna de las distribuciones:

En linux se podría instalar alguna de estas distribuciones pero puede ser más fácil instalar directamente todo lo necesario desde los repositorios. Por ejemplo en Ubuntu:

`sudo apt-get install ipython3 ipython3-notebook spyder python3-matplotlib python3-numpy python3-scipy`

o, en Fedora 28, en adelante:

`sudo dnf install python3-ipython python3-notebook python3-matplotlib python3-numpy python3-scipy`
  • Editores de Texto:

    • En windows: Notepad++, Jedit, … (no Notepad o Wordpad)

    • En Linux: cualquier editor de texto (gedit, geany, kate, nano, emacs, vim, …)

    • En Mac: TextEdit funciona, sino TextWrangler, JEdit, …

  • Editores Multiplataforma e IDEs

    • spyder. (IDE - También viene con Anaconda, y con Python(x,y)).

    • Atom Moderno editor de texto, extensible a través de paquetes (más de 3000).

    • Pycharm. (IDE, una versión comercial y una libre, ambos con muchas funcionalidades)

    • Ninja-IDE (IDE cross-platform, libre)

Documentación y ayudas

Algunas fuentes de ayuda constante son:

Uso de Python: Interactivo o no

Interfaces interactivas (consolas/terminales, notebooks)

Hay muchas maneras de usar el lenguaje Python. Es un lenguaje interpretado e interactivo. Si ejecutamos la consola (cmd.exe en windows) y luego python, se abrirá la consola interactiva

_images/console.png

En la consola interactiva podemos escribir sentencias o pequeños bloques de código que son ejecutados inmediatamente. Pero la consola interactiva estándar no tiene tantas características de conveniencia como otras, por ejemplo IPython que viene con “accesorios de comfort”.

_images/ipython.png

La consola IPython supera a la estándar en muchos sentidos. Podemos autocompletar (<TAB>), ver ayuda rápida de cualquier objeto (?), etc.

Programas/scripts

Una forma muy común/poderosa de usar Python es en forma no interactiva, escribiendo programas o scripts. Esto es, escribir nuestro código en un archivo con extensión .py para luego ejecutarlo con el intérprete. Por ejemplo, podemos crear un archivo hello.py (al que se le llama módulo) con este contenido:

print("Hola Mundo!")

Si ejecutamos python hello.py o ipython hello.py se ejecutará el interprete Python y obtendremos el resultado esperado (impresión por pantalla de “Hola Mundo!”, sin las comillas)

Python no exige un editor específico y hay muchos modos y maneras de programar. Lo que es importante al programar en Python es que la indentación define los bloques (definición de loops, if/else, funciones, clases, etc). Por esa razón es importante que el tabulado no mezcle espacios con caracteres específicos de tabulación. La manera que recomendaría es usar siempre espacios (uno usa la tecla [TAB] pero el editor lo traduce a un número determinado de espacios). La indentación recomendada es de 4 espacios (pero van a notar que yo uso 2).

Un buen editor es Spyder que tiene características de IDE (entorno integrado: editor + ayuda + consola interactiva).

_images/spyder.png

Otro entorno integrado, que funciona muy bien, viene instalado con Canopy.

_images/canopy-cluster.png

También Pycharm funciona muy bien

_images/pycharm.jpg

En todos los casos se puede ejecutar todo el código del archivo en la consola interactiva que incluye. Alternativamente, también se puede seleccionar sólo una porción del código para ejecutar.

Notebooks de Jupyter o Jupyter-Lab

Para trabajar en forma interactiva es muy útil usar los Notebooks de Jupyter. El notebook es un entorno interactivo enriquecido. Podemos crear y editar “celdas” código Python que se pueden editar y volver a ejecutar, se pueden intercalar celdas de texto, fórmulas matemáticas, y hacer que los gráficos se muestren inscrutados en la misma pantalla o en ventanas separadas. Además se puede escribir texto con formato (como este que estamos viendo) con secciones, títulos. Estos archivos se guardan con extensión .ipynb, que pueden exportarse en distintos formatos tales como html (estáticos), en formato PDF, LaTeX, o como código python puro. (.py)

Comandos de Ipython

Comandos de Navegación

IPython conoce varios de los comandos más comunes en Linux. En la terminal de IPython estos comandos funcionan independientemente del sistema operativo (sí, incluso en windows). Estos se conocen con el nombre de comandos mágicos y comienzan con el signo porcentaje %. Para obtener una lista de los comandos usamos %lsmagic:

%lsmagic
Available line magics:
%alias  %alias_magic  %autoawait  %autocall  %automagic  %autosave  %bookmark  %cat  %cd  %clear  %colors  %conda  %config  %connect_info  %cp  %debug  %dhist  %dirs  %doctest_mode  %ed  %edit  %env  %gui  %hist  %history  %killbgscripts  %ldir  %less  %lf  %lk  %ll  %load  %load_ext  %loadpy  %logoff  %logon  %logstart  %logstate  %logstop  %ls  %lsmagic  %lx  %macro  %magic  %man  %matplotlib  %mkdir  %more  %mv  %notebook  %page  %pastebin  %pdb  %pdef  %pdoc  %pfile  %pinfo  %pinfo2  %pip  %popd  %pprint  %precision  %prun  %psearch  %psource  %pushd  %pwd  %pycat  %pylab  %qtconsole  %quickref  %recall  %rehashx  %reload_ext  %rep  %rerun  %reset  %reset_selective  %rm  %rmdir  %run  %save  %sc  %set_env  %store  %sx  %system  %tb  %time  %timeit  %unalias  %unload_ext  %who  %who_ls  %whos  %xdel  %xmode

Available cell magics:
%%!  %%HTML  %%SVG  %%bash  %%capture  %%debug  %%file  %%html  %%javascript  %%js  %%latex  %%markdown  %%perl  %%prun  %%pypy  %%python  %%python2  %%python3  %%ruby  %%script  %%sh  %%svg  %%sx  %%system  %%time  %%timeit  %%writefile

Automagic is ON, % prefix IS NOT needed for line magics.

Algunos de los comandos mágicos

Algunos de los comandos mágicos más importantes son:

  • %cd direct (Nos ubica en la carpeta direct)

  • %ls (muestra un listado del directorio)

  • %pwd (muestra el directorio donde estamos trabajando)

  • %run filename (corre un dado programa)

  • %hist (muestra la historia de comandos utilizados)

  • %mkdir dname (crea un directorio llamado dname)

  • Tab completion: Apretando [TAB] completa los comandos o nombres de archivos.

En la consola de IPython tipee %cd ~ (i.e.%cd” – “espacio” – “tilde”, y luego presione [RETURN]. Esto nos pone en el directorio HOME (default).

Después tipee %pwd (print working directory) y presione [RETURN] para ver en qué directorio estamos:

%pwd
'/home/fiol/Clases/IntPython/clases-python/clases'
%cd ~
/home/fiol
%pwd
'/home/fiol'

En windows, el comando pwd va a dar algo así como:

In [3]: %pwd
Out[3]: C:\\Users\\usuario

Vamos a crear un directorio donde guardar ahora los programas de ejemplo que escribamos. Lo vamos a llamar scripts.

Primero vamos a ir al directorio que queremos, y crearlo. En mi caso lo voy a crear en mi HOME.

%cd
%mkdir scripts
%cd scripts

Ahora voy a escribir una línea de Python en un archivo llamado prog1.py. Y lo vamos a ver con el comando %cat

%cat prog1.py
%run prog1.py
%hist

Hay varios otros comandos mágicos en IPython. Para leer información sobre el sistema de comandos mágicos utilice:

%magic

Finalmente, para obtener un resumen de comandos con una explicación breve, utilice:

%quickref

Comandos de Shell

Se pueden correr comandos del sistema operativo (más útil en linux) tipeando ! seguido por el comando que se quiere ejecutar. Por ejemplo:

comandos

!echo "1+2" >> prog1.py
!echo "print('hola otra vez')" >> prog1.py
%cat prog1.py
%run prog1.py
!date

Ejercicios 01 (a)

  1. Abra una terminal (consola) o notebook y utilícela como una calculadora para realizar las siguientes acciones:

    • Suponiendo que, de las cuatro horas de clases, tomamos dos descansos de 15 minutos cada uno y nos distraemos otros 13 minutos, calcular cuántos minutos efectivos de trabajo tendremos en las 16 clases.

    • Para la cantidad de alumnos presentes en el aula: ¿cuántas horas-persona de trabajo hay involucradas en este curso?

  2. Muestre en la consola de Ipython:

    • el nombre de su directorio actual

    • los archivos en su directorio actual

    • Cree un subdirectorio llamado tmp

    • si está usando linux, muestre la fecha y hora

    • Borre el subdirectorio tmp

  3. Para cubos de lados de longitud L = 1, 3, y 5: calcule su superficie y su volumen.

  4. Para esferas de radios r = 1, 3, 5 y 8, calcule su superficie y su volumen.

  5. Fíjese si alguno de los valores: \(x=0.49\), \(x=0.50\), \(x=0.51\) es un cero de la función \(f(x)=x^{2} + x/2 - 1/2\).


.

Conceptos básicos de Python

Características generales del lenguaje

Python es un lenguaje de uso general que presenta características modernas. Posiblemente su característica más visible/notable es que la estructuración del código está fuertemente relacionada con su legibilidad:

  • Las funciones, bloques, ámbitos están definidos por la indentación

  • Es un lenguaje interpretado (no se compila separadamente)

  • Provee tanto un entorno interactivo como ejecución de programas completos

  • Tiene una estructura altamente modular, permitiendo su reusabilidad

  • Es un lenguaje de tipeado dinámico, no tenemos que declarar el tipo de variable antes de usarla.

Python es un lenguaje altamente modular con una biblioteca standard que provee funciones y tipos para un amplio rango de aplicaciones, y que se distribuye junto con el lenguaje. Además hay un conjunto muy importante de utilidades que pueden instalarse e incorporarse muy fácilmente. El núcleo del lenguaje es pequeño, existiendo sólo unas pocas palabras reservadas:

Las

Palabras

claves

del

Lenguaje

False

class

finally

is

return

None

continue

for

lambda

try

True

def

from

nonlocal

while

and

del

global

not

with

as

elif

if

or

yield

assert

else

import

pass

break

except

in

raise

Tipos de variables

Python es un lenguaje de muy alto nivel y por lo tanto trae muchos tipos de datos ya definidos:

  • Números: enteros, reales, complejos

  • Tipos lógicos (booleanos)

  • Cadenas de caracteres (strings) y bytes

  • Listas: una lista es una colección de cosas, ordenadas, que pueden ser todas distintas entre sí

  • Diccionarios: También son colecciones de cosas, pero no están ordenadas y son identificadas con una etiqueta

  • Conjuntos, tuples, …

Tipos simples: Números

Hay varios tipos de números en Python. Veamos un ejemplo donde definimos y asignamos valor a distintas variables:

a = 13
b = 1.23
c = a + b
print(a, type(a))
print(b, type(b))
print(c, type(c))
13 <class 'int'>
1.23 <class 'float'>
14.23 <class 'float'>

Acá usamos la función type() que retorna el tipo de su argumento. Acá ilustramos una de las características salientes de Python: El tipo de variable se define en forma dinámica, al asignarle un valor.

De la misma manera se cambia el tipo de una variable en forma dinámica, para poder operar. Por ejemplo en el último caso, la variable a es de tipo int, pero para poder sumarla con la variable b debe convertirse su valor a otra de tipo float.

print (a, type(a))
a = 1.5 * a
print (a, type(a))
13 <class 'int'>
19.5 <class 'float'>

Ahora, la variable a es del tipo float.

Lo que está pasando acá en realidad es que la variable a del tipo entero en la primera, en la segunda línea se destruye (después de ser multiplicada por 1.5) y se crea una nueva variable del tipo float que se llama a a la que se le asigna el valor real.

En Python 3 la división entre números enteros da como resultado un número de punto flotante

print(20/5)
print(type(20/5))
print(20/3)
4.0
<class 'float'>
6.666666666666667

Advertencia

En Python 2.x la división entre números enteros es entera

Por ejemplo, en cualquier versión de Python 2 tendremos: 1/2 = 3/4 = 0. Esto es diferente en Python 3 donde 1/2=0.5 y 3/4=0.75.

Nota

La función print

Estuvimos usando, sin hacer ningún comentario, la función

print(arg1, arg2, arg3, ..., sep=' ', end='\n', file=sys.stdout, flush=False)

que acepta un número variable de argumentos. Esta función Imprime por pantalla todos los argumentos que se le pasan separados por el string sep (cuyo valor por defecto es un espacio), y termina con el string end (con valor por defecto newline).

help(print)
Help on built-in function print in module builtins:

print(*args, sep=' ', end='n', file=None, flush=False)
    Prints the values to a stream, or to sys.stdout by default.

    sep
      string inserted between values, default a space.
    end
      string appended after the last value, default a newline.
    file
      a file-like object (stream); defaults to the current sys.stdout.
    flush
      whether to forcibly flush the stream.
print(3,2,'hola')
print(4,1,'chau')
3 2 hola
4 1 chau
print(3,2,'hola',sep='++++',end=' -> ')
print(4,1,'chau',sep='++++')
3++++2++++hola -> 4++++1++++chau

Advertencia

En Python 2.x no existe la función print().

Se trata de un comando. Para escribir las sentencias anteriores en Python 2 sólo debemos omitir los paréntesis y separar la palabra print de sus argumentos con un espacio.

Nota

Disgresión: Objetos

En python, la forma de tratar datos es mediante objetos. Todos los objetos tienen, al menos:

  • un tipo,

  • un valor,

  • una identidad.

Además, pueden tener:

  • componentes

  • métodos

Los métodos son funciones que pertenecen a un objeto y cuyo primer argumento es el objeto que la posee.

Todos los números, al igual que otros tipos, son objetos y tienen definidos algunos métodos que pueden ser útiles.

Números complejos

Los números complejos son parte standard del lenguaje, y las operaciones básicas que están incorporadas en forma nativa pueden utilizarse normalmente

z1 = 3 + 1j
z2 = 2 + 2.124j
print ('z1 =', z1, ', z2 =', z2)
z1 = (3+1j) , z2 = (2+2.124j)
print('1.5j * z2 + z1 = ', 1.5j * z2 + z1)  # sumas, multiplicaciones de números complejos
print('z2² = ', z2**2)  # potencia de números complejos
print('conj(z1) = ', z1.conjugate())
1.5j * z2 + z1 =  (-0.18599999999999994+4j)
z2² =  (-0.5113760000000003+8.496j)
conj(z1) =  (3-1j)
print ('Im(z1) = ', z1.imag)
print ('Re(z1) = ', z1.real)
print ('abs(z1) = ', abs(z1))
Im(z1) =  1.0
Re(z1) =  3.0
abs(z1) =  3.1622776601683795
type(z1)
complex
help(z1)
Help on complex object:

class complex(object)
 |  complex(real=0, imag=0)
 |
 |  Create a complex number from a real part and an optional imaginary part.
 |
 |  This is equivalent to (real + imag*1j) where imag defaults to 0.
 |
 |  Methods defined here:
 |
 |  __abs__(self, /)
 |      abs(self)
 |
 |  __add__(self, value, /)
 |      Return self+value.
 |
 |  __bool__(self, /)
 |      True if self else False
 |
 |  __complex__(self, /)
 |      Convert this value to exact type complex.
 |
 |  __eq__(self, value, /)
 |      Return self==value.
 |
 |  __format__(self, format_spec, /)
 |      Convert to a string according to format_spec.
 |
 |  __ge__(self, value, /)
 |      Return self>=value.
 |
 |  __getattribute__(self, name, /)
 |      Return getattr(self, name).
 |
 |  __getnewargs__(self, /)
 |
 |  __gt__(self, value, /)
 |      Return self>value.
 |
 |  __hash__(self, /)
 |      Return hash(self).
 |
 |  __le__(self, value, /)
 |      Return self<=value.
 |
 |  __lt__(self, value, /)
 |      Return self<value.
 |
 |  __mul__(self, value, /)
 |      Return self*value.
 |
 |  __ne__(self, value, /)
 |      Return self!=value.
 |
 |  __neg__(self, /)
 |      -self
 |
 |  __pos__(self, /)
 |      +self
 |
 |  __pow__(self, value, mod=None, /)
 |      Return pow(self, value, mod).
 |
 |  __radd__(self, value, /)
 |      Return value+self.
 |
 |  __repr__(self, /)
 |      Return repr(self).
 |
 |  __rmul__(self, value, /)
 |      Return value*self.
 |
 |  __rpow__(self, value, mod=None, /)
 |      Return pow(value, self, mod).
 |
 |  __rsub__(self, value, /)
 |      Return value-self.
 |
 |  __rtruediv__(self, value, /)
 |      Return value/self.
 |
 |  __sub__(self, value, /)
 |      Return self-value.
 |
 |  __truediv__(self, value, /)
 |      Return self/value.
 |
 |  conjugate(self, /)
 |      Return the complex conjugate of its argument. (3-4j).conjugate() == 3+4j.
 |
 |  ----------------------------------------------------------------------
 |  Static methods defined here:
 |
 |  __new__(*args, **kwargs) from builtins.type
 |      Create and return a new object.  See help(type) for accurate signature.
 |
 |  ----------------------------------------------------------------------
 |  Data descriptors defined here:
 |
 |  imag
 |      the imaginary part of a complex number
 |
 |  real
 |      the real part of a complex number

Operaciones

Las operaciones aritméticas básicas son:

  • adición: +

  • sustracción: -

  • multiplicación: *

  • división: /

  • potencia: **

  • módulo: %

  • división entera: //

Las operaciones se pueden agrupar con parentesis y tienen precedencia estándar.

División entera (//) significa quedarse con la parte entera de la división (sin redondear).

Nota: Las operaciones matemáticas están incluidas en el lenguaje.

En particular las funciones elementales: trigonométricas, hiperbólicas, logaritmos no están incluidas. En todos los casos es fácil utilizarlas porque las proveen módulos. Lo veremos pronto.

print('división de 20/3:         ', 20/3)
print('parte entera de 20/3:     ', 20//3)
print('fracción restante de 20/3:', 20/3 - 20//3)
print('Resto de 20/3:            ', 20%3)
división de 20/3:          6.666666666666667
parte entera de 20/3:      6
fracción restante de 20/3: 0.666666666666667
Resto de 20/3:             2

Tipos simples: Booleanos

Los tipos lógicos o booleanos, pueden tomar los valores Verdadero o Falso (True o False)

t = False
print('¿t is True?', t == True)
print('¿t is False?', t == False)
¿t is True? False
¿t is False? True
c = (t == True)
print('¿t is True?', c)
print (type(c))
¿t is True? False
<class 'bool'>

Hay un tipo especial, el elemento None.

print ('True == None: ',True == None)
print ('False == None: ', False == None)
a = None
print ('type(a): ',type(a))
print (bool(None))
True == None:  False
False == None:  False
type(a):  <class 'NoneType'>
False

Aquí hemos estado preguntando si dos cosas eran iguales o no (igualdad). También podemos preguntar si una es la otra (identidad):

a = 1280
b = 1280
print(a == b)
print ('b is a: ', b is a)
True
b is a:  False
a = None
b = True
c = a
print ('b is True: ', b is True)
print ('a is None: ', a is None)
print ('c is a: ', c is a)
b is True:  True
a is None:  True
c is a:  True

Acá vemos que None es “único”, en el sentido de que si dos variables son None, entonces son el mismo objeto.

Operadores lógicos

Los operadores lógicos en Python son muy explicitos:

A == B  (A igual que B)
A > B   (A mayor que B)
A < B   (A menor que B)
A >= B  (A igual o mayor que B)
A <= B  (A igual o menor que B)
A != B  (A diferente que B)
A in B  (A incluido en B)
A is B  (Identidad: A es el mismo elemento que B)

y a todos los podemos combinar con not, que niega la condición. Veamos algunos ejemplos

print ('¿20/3 == 6?',20/3 == 6)
print ('¿20//3 == 6?', 20//3 == 6)
print ('¿20//3 >= 6?', 20//3 >= 6)
print ('¿20//3 > 6?', 20//3 > 6)
¿20/3 == 6? False
¿20//3 == 6? True
¿20//3 >= 6? True
¿20//3 > 6? False
a = 1001
b = 1001
print ('a == b:', a == b)
print ('a is b:',a is b)
print ('a is not b:',a is not b)
a == b: True
a is b: False
a is not b: True

Note que en las últimas dos líneas estamos fijándonos si las dos variables son la misma (identidad), y no ocurre aunque vemos que sus valores son iguales.


Warning: En algunos casos Python puede reusar un lugar de memoria.

Por razones de optimización, en algunos casos Python puede utilizar el mismo lugar de memoria para dos variables que tienen el mismo valor, cuando este es pequeño.


a = 11
b = 11
print (a, ': a is b:', a is b)
11 : a is b: True

Este es un detalle de implementación y nuestros programas no deberían depender de este comportamiento.

b = 2*b
print(a, b, a is b)
11 22 False

Acá utilizó otro lugar de memoria para guardar el nuevo valor de b (22).

Esto sigue valiendo para otros números:

a = 256
b = 256
print (a, ': a is b:', a is b)
256 : a is b: True
a = 257
b = 257
print (a, ': a is b:', a is b)
257 : a is b: False

En la implementación que estamos usando, se utiliza el mismo lugar de memoria para dos números enteros iguales si son menores o iguales a 256. De todas maneras, es claro que deberíamos utilizar el símbolo == para probar igualdad y la palabra is para probar identidad.

En este caso, para valores mayores que 256, ya no usa el mismo lugar de memoria. Tampoco lo hace para números de punto flotante.

a = -256
b = -256
print (a, ': a is b:', a is b)
print(type(a))
-256 : a is b: False
<class 'int'>
a = 1.5
b = 1.5
print (a, ': a is b:', a is b)
print(type(a))
1.5 : a is b: False
<class 'float'>

Ejercicios 01 (b)

  1. Para el número complejo \(z= 1 + 0.5 i\)

    • Calcular \(z^2, z^3, z^4, z^5.\)

    • Calcular los complejos conjugados de \(z\), \(z^2\) y \(z^3\).

    • Escribir un programa que escriba las frases:

      • “El conjugado de z=1+0.5i es 1-0.5j”

      • “El conjugado de z=(1+0.5i)^2 es …” (con el valor correspondiente)


.