Archivo de la categoría: Programación

La programación es el proceso de diseñar, codificar, depurar y mantener el código fuente de programas

JDBC

JDBC

JDBC es un conjunto de clases e interfaces Java para la ejecución de sentencias SQL

Es la parte CLI de Java (Call-Level Interface)

Fue desarrollado conjuntamente por JavaSoft, Sybase, Informix e IBM entre otros

JDBC permite la manipulación de cualquier base de datos SQL

No es necesario hacer un programa específico para manipular Oracle, Sybase, etc…

Nuestro programa puede manipular cualquier base de datos

Uniendo Java con JDBC obtenemos programas que se pueden ejecutar en cualquier plataforma y que pueden manipular cualquier base de datos

Las clases e interfaces JDBC se encuentran dentro del paquete java.sql

Proceso de trabajo con JDBC

El proceso de trabajo en JDBC consiste en los siguientes pasos:

  1. Conectarse a la base de datos (mediante DriverManager)

  2. Emitir sentencias SQL (mediante Statement, PreparedStatement, CallableStatement)

  3. Procesamiento de los resultados (ResultSet)

Driver JDBC

Cada base de datos concreta implementa la interface JDBC de una manera particular, al igual que las clases auxiliares y de utilidad que sean necesarias para esa base de datos

Por eso son necesarios los drivers de bases de datos

Una misma aplicación podrá conectar con distintas bases de datos simplemente cambiando ese driver (no debemos confundir el driver de la base de datos con la clase Driver, pues son cosas distintas)

El interface Driver especifica los métodos que todo driver JDBC debe implementar, para ello se pueden cargar los drivers de dos maneras:

  1. Cuando se inicia la clase Driver, el DriverManager consulta la propiedad jdbc.drivers

    Dicha propiedad contiene una lista de drivers (las clases) que deben ser cargadas

    Para ello deberá ejecutarse un comando como este (para usar ODBC) en la línea de comandos:

  2. Si se desea introducir un nuevo driver después de que el DriverManager se halla inicializado se deberá usar el método forname de la clase Class

    Para ello deberemos incluir en nuestro código la siguiente instrucción (para usar ODBC):

    Es aconsejable que se use de forma static en nuestra aplicación (porque sólo se cargará el driver una vez, al cargar la clase)

Ejemplos de drivers
Base de datos Driver
ODBC sun.jdbc.odbc.JdbcOdbcDriver
Oracle oracle.jdbc.driver.OracleDriver
SQLServer com.microsoft.jdbc.sqlserver.SQLServerDriver
MySQL com.mysql.jdbcDriver

Tipos de driver:

  • Puente JDBC-ODBC

    Traduce JDBC a ODBC y lo retransmite al driver ODBC de la máquina

    Es el driver ODBC el que realmente se comunica con la base de datos

    Está incluido en el JDK pero no incluye JDBC2

    Inconvenientes:

    • Es útil para realizar pruebas, pero es lento en producción

    • Es necesario el driver ODBC en el cliente (menor portabilidad)

  • Driver JDBC sobre driver nativo de la BD

    Retransmite JDBC al driver nativo instalado en la máquina

    El driver nativo es el que realmente se comunica con al base de datos

    Inconveniente:

    • necesidad de driver nativo (menor portabilidad)
  • Driver Java sobre red

    Traduce las llamadas JDBC a un protocolo de red independiente de la plataforma que contacta con el servidor

    El servidor traduce esas peticiones al protocolo concreto de cada base de datos

    Se usa un middleware en el servidor de red que es capaz de conectar a los clientes puros Java a muchas bases de datos diferentes

    Ventaja:

    • es rápido, independiente de la plataforma y no requiere de instalación en el cliente

  • Driver puro Java con protocolo nativo

    Traduce las llamadas JDBC al protocolo específico de la base de datos contactando directamente con ella

Obtener conexiones

Mediante el driver concreto realizaremos las conexiones, pero las solicitudes de conexión deben ser realizadas mediante el DriverManager

Una vez que la clase Driver ha sido cargada y registrada, el DriverManager puede establecer conexiones con la base de datos mediante estos dos pasos:

  1. Se llama al método DriverManager.getConnection(url, user, pass); y se obtiene un objeto de tipo Connection

  2. El DriverManager prueba los drivers registrados para ver si puede establecer la conexión y si no fue posible, lanza una SQLException

Una misma aplicación, puede tener varias conexiones a la misma base de datos o varias conexiones a otras bases de datos (hasta el máximo permitido por la base de datos)

Los parámetros que admite getConnection son la url (que es un subprotocolo que utiliza la base de datos para realizar la conexión), el user (el nombre de usuario que va a conectarse) y el pass (la contraseña que utiliza el usuario para conectarse)

El parametro url tiene el siguiente formato:

El subprotocolo es particular de cada base de datos y lo utiliza el DriverManager para buscar el driver adecuado para manipularla

El subnombre depende del subprotocolo concreto

El driver será el encargado de interpretarlo y le ayudará a localizar la base de datos

Nuestra aplicación no trabajará con el driver concreto, sino que lo hará el DriverManager

De esta manera las aplicaciones pueden trabajar con el objeto Connection sin preocuparse por el tipo de base de datos con la cual estemos trabajando (no hay que hacer modificaciones en el código, solo cambiar el parámetro url)

La conexión debe cerrarse siempre al finalizar, porque sino se consumen recursos de forma innecesaria, aunque se pueden reutilizar conexiones, no es aconsejable, es mejor usar siempre una conexión nueva

En el ejemplo se ha utilizado un esqueleto de conexión para Oracle

Para utilizar la conexión debemos crear un objeto de tipo Connection, el cual representa una sesión abierta con la base de datos

El objeto provee de un contexto con el que poder emitir sentencias SQL y obtener resultados

El objeto Connection debe inicializarse inicialmente a null, así podremos comprobar si hubo conexión porque incluiremos un bloque try para gestionar errores, el cuál lanzará SQLException

Para cerrar la conexión debe hacerse mediante el método close(), dentro de un finaly (el cual también tendrá su bloque try que lanza SQLException)

El interface Statement

La conexión nos permite crear objetos Statement mediante el método createStatemen()

Los objetos Statement permiten la ejecución de sentencias SQL y la obtención de resultados (mediante los objetos ResultSet)

Los métodos para ejecutar SQL aceptan String como parámetro (JDBC es CLI), los cuales pueden componerse dinámicamente en función de valores contenidos en variables

Para componer el String SQL habrá que concatenar los distintos fragmentos SQL (los estáticos y las variables)

Hay tres formas de ejecutar sentencias SQL:

  1. Mediante el método executeQuery(<sql>) para consultas mediante la sentencia SELECT que produce túplas como resultado (devuelve un objeto de tipo ResultSet)

    • Es como una tabla que almacena el resultado de la consulta

    • Tiene una serie de métodos de consulta

    • Es como un cursor (en terminología PL / SQL)

  2. Mediante el método executeUpdate(<sql>) para actualizaciones mediante las sentencias INSERT, DELETE, UPDATE, así como comandos DDL (CREATE, DROP, ALTER TABLE, ADD) y bloques PL / SQL (entre los bloques begin y end)

    • Devuelve un entero que indica el número de filas modificadas por el comando

    • Con los comandos DDL devuelve 0

  3. Mediante el método execute(<sql>) que ejecuta cualquier sentencia SQL

    • Si se utilizó un QUERY, devolverá True

      • El ResultSet se puede obtener mediante el método getResultSet()

    • Si se utilizó un UPDATE, devolverá False

      • El total de filas modificadas se pueden obtener mediante el método getUpdateCount()

Después de procesar el resultado, se debe cerrar el Statement mediante el método close()

Este método cierra también el ResultSet asociado, de todas formas, Sun recomendaba cerrar el ResultSet de forma explícita para evitar errores no deseados

Un mismo Statement puede reutilizarse en una misma conexión para ejecutar distintas sentencias

El interface ResultSet

El objeto ResultSet actúa como un cursor dentro de los resultados

La primera vez que se lee apunta encima del primer resultado, pero no lo lee, por eso hay que leer la primera fila avanzando mediante el método next()

El método next() devuelve True si pudo avanzar o False si no pudo

Para obtener los valores del ResultSet se utilizan los métodos get que tienen el siguiente formato get<tipo>(<columna>)

Para nombrar las columnas podemos o hacerlo por su nombre o por un indice, el cual empieza en 1, su numeración viene dada por el orden en que fue introducida en el SELECT

Hay que prestar atención a las fechas, porque se guardan como java.sql.Date, no como java.util.Date como se podría esperar

Conviene cerrar el ResultSet aunque se cierra implícitamente al cerrar o reutilizar el Statement que lo creó

Cuando se ha leído un null de SQL usando uno de los métodos get<tipo>, éste devuelve:

  • Un valor null de Java para aquellos métodos que devuelven objetos Java (getString(), getBigDecimal(), getDate(), getTime(), getTimestamp(), getObject(), etc)

  • Un valor 0 para aquellos métodos que devuelven tipos numéricos (getByte(), getShort(), getInt(), getLong(), getFloat(), getDouble() )

  • Un valor False para el método getBoolean()

Para determinar si un valor dado era null, primero debe intentar leerse la columna y usar el método de ResulSet wasNull() para saber si fue null

Devolverá True si lo era, False en caso contrario

El interface PreparedStatement

Cada vez que se lanza un Statement la base de datos debe interpretarla y calcular un plan de consulta

Pero al usar PreparedStatement, se puede ejecutar múltiples veces, obteniendo un aumento de rendimiento al tener la consulta ya analizada y optimizada

No todas las bases de datos soportan PreparedStatement, hay que leer la documentación de la misma para saber si se pueden usar

Los objetos PreparedStatement derivan del Statement obtenido de la conexión, mediante el método prepareStatement(<sql>);

Un PreparedStatement sirve para lanzar instrucciones SQL precompiladas, podremos parametrizar una o más entradas mediante el operador ?, cuyos valores podrán ser modificados en distintas ejecuciones de la instrucción

Parametrizar las entradas es útil cuando desconocemos los valores de ciertos tipos de datos SQL en la base de datos de destino,

El valor parametrizado obtiene el valor correcto del driver de la base de datos, por lo que no deberemos preocuparnos por los tipos

Antes de que la instrucción SQL pueda ser ejecutada deberemos asignarle un valor a los parámetros de entrada

Para asignar valores usaremos los métodos set<tipo>(columna, valor); siendo el tipo compatible con el del parámetro

Para ejecutarlo se usan los métodos execute de Statement

En el ejemplo se ha utilizado un PreparedStatement para Oracle

Python

Python

Python es un lenguaje de programación muy utilizado actualmente en entornos relacionados con Data Science y Big Data

Su uso en librerías creadas por Google y otros gigantes tecnológicos ha hecho que en los últimos años se haya convertido en uno de los lenguajes más utilizados

Dentro de los lenguajes de programación, sus características son:

  • Interpretado

    El proceso de compilado es el de traducción del lenguaje de programación que estemos utilizando (por ejemplo C++) a código máquina que el ordenador puede ejecutar

    Además, en este proceso se crea un archivo ejecutable que puede utilizarse en otros ordenadores

    Hay lenguajes de programación que no utilizan un proceso de compilado sino un intérprete, que añade significado a las sentencias programadas

    Python es un lenguaje interpretado

  • Tipado dinámico

    El tipado de un lenguaje de programación es la forma que tiene el lenguaje de gestionar las variables y sus tipos

    Por lo general, en un lenguaje de programación se pueden crear variables de diferentes tipos (numero entero, número real, carácter, listas…)

    Existen lenguajes en los que antes de poder utilizar una variable tenemos que definirla y asignarle un tipo concreto de variable

    En un lenguaje no formal sería algo como: Quiero una variable entera que se llame Hermanos y Asigna a la variable casa el valor 3

    Sin embargo en Python no es necesario realizar esta asignación, dado que es un lenguaje con tipado dinámico y, en general, no es necesario definir una variable para poder utilizarla

    En Python escribiríamos directamente La variable hermanos tiene un valor de 2 y sería el interprete quien vería que queremos utilizar una variable que no existe, con el nombre Hermanos y asignarle el valor 2

  • Multi paradigma

    Existen varias formas de programar; con programación orientada a objetos como programación funcional

    Python admite ambos tipos

  • Multi plataforma

    Existen intérpretes de Python para múltiples plataformas, tales como MS Windows, Mac OS o Linux

Tanto el intérprete de Python como su extensa biblioteca estándar están a libre disposición en forma de código fuente y archivo ejecutable para las principales plataformas desde el sitio web de Python

Detrás de Python existe una amplia comunidad que provee amplio soporte a la vez que desarrolla y actualiza constantemente una miriada de librerías centralizado en un repositorio llamado Pypi

Ademas existe un código de buenas prácticas de programación en Python así como una guía de estilo, a fin de que el código sea de fácil lectura y comprensión

Instalación y modos de uso de Python

Python puede instalarse en nuestro ordenador desde la página de Python (recomendado instalar la última versión de Python)

Sin embargo, es más cómodo realizar la instalación mediante una distribución como Anaconda, que nos descarga el intérprete, diferentes editores y los paquetes y librerías más utilizados

Para instalar esta distribución tendríamos que:

  1. Ir a la página de descargas de Anaconda y descargar el paquete que se ajusta a tu sistema operativo y versión de Python deseada

    Se recomienda instalar la correspondiente a la versión más actual de Python

  2. Ejecutar el paquete y dejar que se instale completamente en el sistema
  3. Tras la instalación sería recomendable actualizar los paquetes

    Para ello abre un terminal y ejecuta:

    Mostrará una lista de librerías que van a a ser actualizadas

    Si estás conforme, acepta e iniciará la descarga y la instalación de las librerías

  4. En el caso de querer instalar una librería concreta, en el terminal ejecutaremos:

    Instalará la última versión de la librería presente en el repositorio de Anaconda que corresponda a nuestro sistema operativo y a nuestra versión de Python

En caso de que no esté presente en los repositorios, opcionalmente podemos instalar la librerías con pip

Para ello abre un terminal y ejecuta:

Para más información consultar la documentación de Anaconda

La forma más rápida de utilizar Python es mediante línea de comandos

Una vez tenemos un intérprete instalado en nuestro ordenador, abriríamos un terminal y escribiríamos

Esto abre una consola sobre la que podemos escribir y ejecutar código Python

Cada línea que ejecutásemos se realizaría la operación solicitada

Es una forma muy rápida para testear código pero es muy poco práctica, ya que perdemos la reutilización del código ejecutado

Es decir, si quisiésemos ejecutarlo de nuevo, tendríamos que escribir linea a linea el código otra vez

Lo más común es utilizar un editor como Spyder (se instala junto a Anaconda) o Jupyter notebooks, que es el que voy a utilizar yo para los ejemplos

Jupyter Notebook

Jupyter Notebook (anteriormente, IPython Notebook) es una aplicación web de código abierto que te permite crear y compartir documentos que contienen código en vivo, ecuaciones, visualizaciones y texto narrativo

Además, es una aplicación muy utilizada en el campo de la Ciencia de Datos (Data Science) para crear y compartir documentos que incluyen: limpieza y transformación de datos, simulación numérica, modelado estadístico, visualización de datos, aprendizaje automático y mucho más

Te permite editar y ejecutar documentos de notebook a través de cualquier navegador web de tu elección; y puede ejecutarse en un escritorio local que no requiere acceso a Internet o puede instalarse en un servidor remoto y acceder a través de Internet

También podemos ejecutar Jupyter Notebook sin ninguna instalación desde la página web del proyecto

O instalarlo usando pip, para ello abre un terminal y ejecuta:

Utilizar Jupyter Notebook

Una vez lo tengamos instalado, abriremos un terminal y ejecutaremos:

Esto imprimirá cierta información sobre el servidor de notebook en nuestro terminal, incluida la URL de la aplicación web (de forma predeterminada, http://localhost:8888)

En caso de necesitar conocer la ruta en la que tenemos instalado Jupyter, podemos ejecutar en el terminal:

En caso de necesitar conocer la versión de Python que tenemos instalado, podemos ejecutar en el terminal:

Antes de ejecutar este comando de una línea, se recomienda que verifiquemos que nuestro directorio de Anaconda PATH se haya agregado correctamente a las Variables de entorno, y si no es así, debemos ubicar nuestra ruta de directorio / archivo de Anaconda y agregarlo a las Variables de entorno, o si no podrías obtener un error:

jupyter no se reconoce como un comando interno o externo

Si el lanzamiento ha funcionado correctamente, se abrirá nuestro navegador por defecto con el Notebook abierto en el puerto 8888

Una vez ya dentro del Notebook, observaremos un botón llamado New que, al hacer clic, nos permite seleccionar un kernel de Python (las opciones dependen de lo que esté instalado en nuestro servidor local) del menú desplegable

Se recomienda seleccionar la última versión de Python que nos aparezca en el desplegable, a no ser que sea necesario usar otra por motivos de compatibilidad

Una vez seleccionado y aceptado, se nos abrirá nuestro primer cuaderno para escribir nuestros programas en Python

Nuestro primer script Python

Vamos a escribir un pequeño script de ejemplo para mostrar lo sencillo que es ejecutar un script Python desde Jupyter

Python tiene definido un sistema de almacenamiento y gestión de variables

En las variables podemos guardar información que queramos utilizar más adelante en el código con un nombre que nos sea fácil de recordar

En nuestro ejemplo, queremos calcular el área y el volumen de una esfera

Las ecuaciones que necesitamos son:

  • A = 4\pi \cdot r^2 para el área
  • V = \frac{4}{3}\pi \cdot r^3 para el volumen

En concreto, queremos calcular estos valores para una esfera de 7 de radio

Vamos a definir tres variables:

  • r

    Contiene el valor del radio, en este caso 7

  • A

    Contiene el valor del área calculada

  • V

    Contiene el valor del volumen calculado

¿Qué ventajas obtenemos definiendo variables?

Si cambiamos de idea y en vez de un radio 7 queremos que sea 6, tendríamos que cambiar el número de dos sitios (que en el caso de un programa en producción podrían ser cientos)

O queremos que sea el usuario quien indique el valor, de forma que no podemos saberlo a priori

Para escribirlo en Python usaremos una celda del cuaderno a la que le asignaremos en el menú desplegable (lo veremos a la izquierda del icono que parece un teclado) el valor Code

Una vez dentro de la celda, la usaremos como un editor de texto escribiendo:

Para ejecutarlo podemos usar el botón run o dejando pulsada la tecla de mayúsculas y después pulsando enter

El resultado de las variables permanecerá en memoria, pero nosotros no podremos verlo

Ahora vamos a usar la función print (similar a la función de C++) para poder ver el resultado de nuestro script Python

Para poder usar la constante Pi, se ha importado el módulo math con la sentencia import math y luego la hemos usado con math.pi

Como puede verse, para definir una variable escribimos el nombre con el que queremos bautizarla, el signo = y la expresión que queremos que sea asignada a esa variable

Comentarios en Python

Python soporta comentarios tipo Shell de Unix

Operadores en Python

Operadores en Python

Python posee operadores aritméticos, relacionales, lógicos, bit a bit, de asignación, pertenencia e identidad

Operadores aritméticos

Python suministra las operaciones básicas con los únicos añadidos de los operadores resto, cociente entero y exponenciación

Operadores aritméticos
Operador Operación Descripción
+ Suma Suma dos operandos
Resta

Resta al operando de la izquierda el valor del operando de la derecha

Utilizado sobre un único operando, le cambia el signo

* Multiplicación Multiplicación de dos operandos
/ División Divide el operando de la izquierda por el de la derecha (el resultado siempre es un float)
% Resto Obtiene el resto de dividir el operando de la izquierda por el de la derecha
// Cociente entero Obtiene el cociente entero de dividir el operando de la izquierda por el de la derecha
** Exponenciación El resultado es el operando de la izquierda elevado a la potencia del operando de la derecha

Nota En Python, usar el operador + aplicado a strings, concatena ambas strings en una sola

Operadores relacionales

Se emplean típicamente en las expresiones condicionales

Los operadores relacionales devuelven valores booleanos

Los operandos pueden ser tanto numéricos como strings

Operadores relacionales
Operador Operación Descripción
> Mayor que

True si el operando de la izquierda es estrictamente mayor que el de la derecha

False en caso contrario

< Menor que

True si el operando de la izquierda es estrictamente menor que el de la derecha

False en caso contrario

> = Mayor o igual que

True si el operando de la izquierda es mayor o igual que el de la derecha

False en caso contrario

< = Menor o igual que

True si el operando de la izquierda es menor o igual que el de la derecha

False en caso contrario

! = Distinto que

True si los operandos son distintos

False en caso contrario

= = Igual que

True si el operando de la izquierda es igual que el de la derecha

False en caso contrario

Los objetos de diferentes tipos, excepto los tipos numéricos, nunca se comparan igual

El operador == siempre está definido, pero para algunos tipos de objetos (por ejemplo, objetos de clase) es equivalente a is

Las instancias no idénticas de una clase normalmente se comparan como no iguales a menos que la clase defina el método __eq__()

Las instancias de una clase no se pueden ordenar con respecto a otras instancias de la misma clase u otros tipos de objeto, a menos que la clase defina los métodos __lt__() y __gt__()

Operadores lógicos

Los operandos lógicos está relacionados con los relacionales ya que normalmente los operandos que usan son resultado de expresiones relacionales

Los valores resultantes son booleanos

Operadores lógicos
Operador Descripción
AND True si ambos son True
OR True si uno de ellos es True
NOT Si era True pasa a False y viceversa

Operadores bit a bit

La forma de trabajar de estos operadores es convertir a binario los operandos y luego operar con ellos bit a bit

Operadores bit a bit
Operador Operación Descripción
& AND Cambia el bit a 1 si ambos eran 1
| OR Cambia el bit a 1 si uno de ellos era 1
^ XOR Cambia el bit a 1 si uno de ellos era 1, pero no ambos
~ NOT

Cambia el bit a 1 si era 0

Cambia el bit a 0 si era 1

<< Propagación a la izquierda Desplaza el valor hacia la izquierda introduciendo ceros, si se sale de rango se pierden valores
>> Propagación a la derecha Desplaza el valor hacia la derecha introduciendo por la izquierda el bit de signo y eliminando los valores que se salgan por la derecha

Nota Los operadores de propagación toman dos operandos: el primero es la variable a propagar y el segundo es el número de posiciones a propagar

Operadores de asignación

La asignación también es un operador que devuelve la variable modificada

El operador de asignación en Python es =

Los operadores de asignación que se muestran a continuación no son sino abreviaturas que hacen más cómoda y simples las expresiones, aunque a veces sean más ilegibles

Operadores de asignación
Operador Expresión Equivalencia
=

A = B = C

D = ‘Texto’

A = C

B = C

D = ‘Texto’

+ = A + = 4 A = A + 4
– = A – = 3 * B A = A – (3 * B)
* = A * = 2 A = A * 2
** = A ** = 2 A = A ** 2
/ = A / = 35 + B A = A / (35 + B)
% = A % = B A = A % B
// = A // = B A = A // B
>> = A >> = 1 A = A >> 1
<< = A << = B A = A << B
& = A & = (C + = 3) C = C +3
A = A & C
^ = A ^ = 2 A = A ^ 2
| = A | = C A = A | C

Operadores de pertenencia

Los operadores de pertenencia se utilizan para comprobar si un valor o variable se encuentran en una secuencia (list, tuple, dict, set o str)

Operadores de pertenencia
Operador Expresión Equivalencia
in Incluido

Devuelve True si el valor se encuentra en una secuencia

False en caso contrario

not in No incluido

Devuelve True si el valor no se encuentra en una secuencia

False en caso contrario

Operadores de identidad

Estos operadores se van a utilizar para comprobar si dos variables son, o no, el mismo objeto

Operadores de pertenencia
Operador Expresión Equivalencia
is Objetos iguales

Devuelve True si ambos operandos hacen referencia al mismo objeto

False en caso contrario

is not Objetos distintos

Devuelve True si ambos operandos no hacen referencia al mismo objeto

False en caso contrario

Preferencia

La preferencia de los operadores va a determinar el orden en que se ejecuten en una expresión determinada

Usando paréntesis controlaremos que las operaciones se lleven a cabo según nosotros queramos

En Python la preferencia de los operadores de mayor a menor es la siguiente:

Preferencia
Paréntesis ( )
Exponenciación **
Unarios ~ +
Mul / Div / Resto / Div ent * / % //
Suma / Resta +
Propagación << >>
Bit a bit &
Bit a bit ^ |
Relacionales < < = > > =
Igualdad = = !=
Asignación = + = – = * = * * = / = // = % = & = | = ^ = >> = << =
Identidad is is not
Pertenencia in not in

Tipos de datos en Python

Tipos de datos en Python

Los tipos en Python son una representación de los datos, ya que no requiere que las variables declaren su tipo, porque todos los tipos se convierten de forma automática

Podemos utilizar la función type para conocer el tipo de una variable

Tipo booleano

El tipo booleano simplemente distingue entre dos estados, un estado de éxito o de activado, valor verdadero, True, y un estado de fracaso o de desactivado, valor falso, False

Ambos estados no son susceptibles a mayúsculas y minúsculas

Normalmente, el resultado de operadores que devuelven un valor de tipo booleano son pasados a las estructura de control

Tipos numéricos

En Python existen 4 tipos diferentes de variables numéricas:

  • int

    número entero con precisión fija

  • long

    número entero en caso de sobrepasar el tamaño de un int

  • float

    número en coma flotante de doble precisión

  • complex

    número complejo (parte real + j parte imaginaria)

Es el intérprete el que decide el tipo de variable según lo que definimos

Sin embargo, podemos querer forzarlo nosotros mediante un cast

Tipo string

Un string es una cadena de caracteres delimitadas por comillas

Un literal de tipo string se puede especificar de dos formas diferentes:

  • entrecomillado simple

    se especifican entre los carácteres de apertura y de cierre

    Para especificar una comilla simple literal, se ha de escapar con una barra invertida (\). Para especificar una barra invertida literal, se duplica (\\)

    Todas las demás instancias de barras invertidas serán tratadas como una barra invertida literal: esto significa que otras secuencias de escape que podrían utilizarse, tales como \r o \n, serán mostradas literalmente tal y como se especifican, en lugar de tener cualquier otro significado especial

  • entrecomillado doble

    se especifican entre los carácteres " de apertura y " de cierre

    Python interpretará las siguientes secuencias de escape como caracteres especiales:

    Código Descripción
    \n avance de línea (LF o 0x0A (10) en ASCII)
    \r retorno de carro (CR o 0x0D (13) en ASCII)
    \t tabulador horizontal (HT o 0x09 (9) en ASCII)
    \\ barra invertida
    \" comillas dobles

Métodos

Vamos a ver algunos de los métodos para cadenas de uso más cotidiano

Métodos de formato

Afectan al formato del texto contenido en la cadena

  • capitalize()

    Realiza una copia de la cadena con la primera letra en mayúsculas

  • lower()

    Devuelve una copia de la cadena en minúsculas

  • upper()

    Devuelve una copia de la cadena en mayúsculas

  • swapcase()

    Devuelve una copia de la cadena en la que las mayúsculas son minúsculas y viceversa

  • title()

    Devuelve una copia de la cadena en la que la primera letra de cada palabra es mayúscula y las demás minúsculas

  • center(longitud, ‘caracter de relleno’)

    Devuelve una copia de la cadena de entrada centrada en la longitud indicada y entre el caracter de relleno que se indique

  • ljust(longitud, ‘caracter de relleno’): Devuelve una copia de la cadena alineada a la izquierda

  • rjust(longitud, ‘caracter de relleno’)

    Devuelve una copia de la cadena alineada a la izda/derecha

  • zfill(longitud)

    Devuelve una copia de la cadena rellenada con ceros a la izda hasta alcanzar la longitud indicada

Métodos de búsqueda

Nos permiten buscar dentro de una determinada cadena para comprobar si una subcadena está contenida en la cadena o cuántas veces aparece una subcadena

  • count(‘subcadena’)

    Devuelve un entero representando la cantidad de apariciones de la subcadena dentro de la cadena

  • find(‘subcadena’)

    Devuelve un entero representando la posición en la que empieza la subcadena dentro de la cadena

Métodos de validación

Nos devuelven siempre un booleano, es decir, True o False

Sirven para comprobar si una cadena cumple una determinada condición

  • startswith(‘subcadena’)

    Nos dice si una cadena comienza por una cadena determinada

  • endswith(‘subcadena’)

    Nos dice si una cadena termina por una cadena determinada

  • isalnum()

    Nos dice si una subcadena es alfanumérica

  • isalpha()

    Nos dice si una cadena es alfabética

  • isdigit()

    Nos dice si una cadena es numértica

  • islower()

    Nos dice si una cadena contiene sólo minúsculas

  • isupper()

    Nos dice si una cadena contiene sólo mayúsculas

  • isspace()

    Nos dice si una cadena contiene sólo espacios en blanco

  • istitle()

    Nos dice si una cadena tiene formato de título

Métodos de sustitución

Nos permiten sustituir texto para unificar el formato de diferentes cadenas que nos han llegado por vías diferentes

  • format(argumentos)

    Podemos tener una cadena que esté preparada para recibir una cierta cantidad de argumentos

    Al llamar a esta función e introducir los argumentos necesarios nos devuelve una copia de la cadena ya formateada

  • replace(‘subcadena buscada’, ‘subcadena que poner’)

    Busca dentro de la cadena una subcadena y la sustituye por la cadena indicada

  • strip()

    Elimina el carácter que indiquemos de la derecha y de la izquierda de la cadena

    Por defecto busca el carácter espacio

  • lstrip()

    Elimina los caracteres a la izquierda de una cadena

    Si introducimos como argumento una subcadena, busca esa subcadena y las combinaciones de los caracteres de la subcadena desde la izquierda hasta que no encuentre ninguno más

  • rstrip()

    Elimina los caracteres a la a derecha de una cadena

    Si introducimos como argumento una subcadena, busca esa subcadena y las combinaciones de los caracteres de la subcadena desde la derecha hasta que no encuentre ninguno más

Métodos de unión y división

Nos permiten sustituir texto para unificar diferentes cadenas que nos han llegado por vías diferentes o para separar una cadena en varias

  • join(iterable)

    Recibe como argumento un iterable y devuelve como resultado los elementos del iterable unidos por el carácter de la cadena sobre la que se aplica

  • partition(‘separador’)

    Devuelve una tupla de 3 elementos

    El primer elemento es lo que hay a la izquierda del ‘separador’, el segundo elemento es el separador y el tercer elemento es lo que hay a la derecha del separador

  • split(‘separador’)

    Devuelve una lista con todos los elementos encontrados al dividir la cadena por el separador

  • splitlines()

    Devuelve una lista donde cada elemento es una fracción de la cadena dividida en líneas

Listas

Se definen poniendo el contenido de la lista entre corchetes, separando cada uno de los elementos mediante una coma

Cada posición de la lista puede contener elementos de distinto tipo

Las listas son mutables, es decir, sus elementos pueden ser modificados

En Python los elementos de una lista se numeran desde 0 hasta longitud – 1

Para acceder al elemento de una lista se pone el nombre de la lista y a continuación el índice al que queremos acceder (si ponemos el índice con signo negativo empezará por el final de la lista)

Para acceder a un rango dentro de una lista tenemos diferentes opciones:

  • Tomar elementos desde el inicio: lista[:a]
  • Tomar elementos desde la posición a (incluida) hasta el final: lista[a:]
  • Tomar elementos desde a hasta b (sin incluir b): lista[a:b]

El inicio del rango siempre incluye el elemento en esa posición, pero no el final del rango

Métodos

Vamos a ver algunos de los métodos para listas de uso más cotidiano

  • append()

    añade un elemento al final de la lista

  • insert()

    se usa para insertar un elemento en el índice asignado

  • pop()

    elimina y devuelve el valor en la posición del índice asignado

  • reverse()

    reordena la lista de forma reversa

  • sort()

    reordena la lista de forma ascendente

Podemos encontrar todos los métodos en su documentación

Tuplas

Las tuplas son similares a las listas, se definen con paréntesis en vez de corchetes

Tienen la peculiaridad de ser inmutables

Como puede verse, se accede a los elementos de igual forma que con las listas

Diccionarios

Los diccionarios definen una relación de uno a uno entre clave valor entre {} y son mutables

Se definen colocando una lista separada por comas de pares clave:valor

Una vez definido, podemos acceder al valor asociado a una clave buscando por clave

Además, podemos buscar si una determinada clave existe o no en nuestro diccionario

Los diccionarios son un tipo de colección en Python que, a diferencia de las listas, están indexadas por palabras y no por números

Los valores pueden ser de cualquier tipo

Podemos pensar en un diccionario como un conjunto no ordenado de pares clave:valor con el requisito de que las claves tienen que ser únicas

Métodos

Vamos a ver algunos de los métodos para diccionarios de uso más cotidiano

  • keys()

    nos devuelve un iterable que contiene las claves del diccionario

  • values()

    nos devuelve un iterable que contiene los valores del diccionario

  • items()

    nos devuelve un iterable con los pares clave:valor del diccionario

Objetos

Los objetos se componen de un conjunto de valores, propiedades y un conjunto de métodos aplicados a esos valores

Son estos métodos los que nos permiten modificar el estado de dicho objeto, es decir, el valor de sus propiedades

En Python los objetos tiene las siguientes particularidades:

  • Todo es un objeto, incluyendo los tipos y clases
  • Permite herencia múltiple
  • No existen métodos ni atributos privados
  • Los atributos pueden ser modificados directamente
  • Permite monkey patching

    Las clases se crean en tiempo de ejecución pero pueden modificarse tras ser creadas

  • Permite duck typing

    El estilo de tipificación dinámica de datos en que el conjunto actual de métodos y propiedades determina la validez semántica, en vez de que lo hagan la herencia de una clase

  • Permite la sobrecarga de operadores
  • Permite la creación de nuevos tipos de datos

Vamos a crear un objeto Universitario de ejemplo en el que tendremos las propiedades: Nombre, Apellido, Edad y Dni

La instancia del objeto la crearemos mediante la asignación a una variable de la siguiente forma:

Es posible consultar la clase de un objeto con la función type, pero también se puede consultar a través de su atributo especial __class__

A su vez las clases tienen un atributo especial __name__ que nos devuelve su nombre en forma de cadena sin adornos:

Es posible inicializar todas las variables para que tengan el tipo que queremos, para ello usaremos el constructor de la clase pasándole los argumentos que necesitemos

El constructor es un método que se llama automáticamente al crear un objeto y se define con el nombre __init__ y mediante la palabra reservada self podremos referenciar al objeto actual

Si existe un constructor también debe existir un destructor que se llame al eliminar el objeto para que encargue de las tareas de limpieza como vaciar la memoria

Todos los objetos se borran automáticamente de la memoria al finalizar el programa, aunque para eliminarlos automáticamente disponemos del método especial __del__

No es aconsejable sobreescribir este método porque se maneja automáticamente, pero es interesante saber que es posible

El método __str__ es el que devuelve la representación de un objeto en forma de cadena

Se llama automáticamente es cuando imprimirmos una variable por pantalla con la función print

Por defecto los objetos imprimen su clase y una dirección de memoria, pero podemos cambiarlo sobreescribiendo su comportamiento

Por ejemplo, para el objeto universitario sobreescribimos el método __str__ para que nos muestre el nombre, edad, apellidos y dni

Un método especial interesante es el que devuelve la longitud

Normalmente está ligado a colecciones, pero nada impide definirlo en una clase y no redefinirlo, porque por defecto no existe en los objetos aunque sea el que se ejecuta al pasarlos a la función __len__

En nuestro ejemplo del objeto universitario no tiene mucho sentido contar su longitud, pero lo incluyo para mostrar su uso

Las propiedades de un objeto pueden describirse mediante otros objetos o incluso colecciones de ellos

La definición de métodos asociados a un objeto puede precisarse en la definición del objeto

Por ejemplo, para el objeto universitario sobreescribimos el método __str__ para que muestre el nombre, edad, apellidos, dni y notas medias del alumno

Para acceder a las propiedades o a los métodos usaremos el operador .

Herencia

La herencia es la capacidad que tiene una clase de heredar los atributos y métodos de otra, algo que nos permite reutilizar código

Para ver su utilidad, vamos a desarrollar un ejemplo modificando el objeto universidad

Partiremos de una clase base que hará de padre (superclase) de otras hijas que heredaran de ella (subclases)

Partimos de una clase Persona que contendrá todos los atributos comunes y dos clases hijas Alumno y Profesor que heredan de ella y tienen atributos o métodos propios

Para heredar los atributos y métodos de una clase en otra sólo tenemos que pasarla entre paréntesis durante su definición

Es posible utilizar el comportamiento de una superclase sin definir nada en la subclase, aunque en nuestro ejemplo si que les daremos comportamiento

Gracias a la flexibilidad de Python podemos manejar objetos de distintas clases masivamente de una forma muy simple

Vamos a empezar creando una lista con nuestros dos Personas de subclases distintas

Uno de los pocos fallos de Python es que si modificamos los valores dentro de un objeto, estos cambios se verán reflejados fuera del mismo

De la misma forma que en las colecciones, los objetos se pasan a las funciones por referencia

Afecta a la hora de hacer copias, creándose en su lugar un acceso al objeto en lugar de uno nuevo con sus valores anteriores

Para realizar una copia a partir de sus valores podemos utilizar la función copy del módulo con el mismo nombre

La función copy se puede utilizar también para copiar colecciones

La herencia múltiple permite a una subclase heredar de múltiples superclases

Esto conlleva un problema, y es que si varias superclases tienen los mismos atributos o métodos, la subclase sólo podrá heredar de una de ellas

Además de superclases también puede heredar de forma múltiple de subclases

En estos casos Python dará prioridad a las clases más a la izquierda en el momento de la declaración de la subclase

Hemos usado la palabra reservada pass para indicarle al intérprete que ignore el código del cuerpo y utilice el de la clase object o el de las superclases (subclases) que le indiquemos

Valor nulo

En Python a las variables se les puede asignar un valor que indica el valor vacío, este valor es el valor NULL

Una variable es considerada None si:

  • se le ha asignado la constante None
  • no se le ha pasado un atributo a una función

La constante None es insensible a mayúsculas o minúsculas

Estructuras de control en Python

Estructuras de control en Python

Para las estructuras de control, Python posee las sentencias de control típicas de los lenguajes de alto nivel

Declaración de variables

A las variables en Python no se les asigna un tipo predefinido

En Python el tipo de las variables depende del valor que contengan las mismas en cada momento

Por tanto se realiza una conversión automática de tipos

Python reconoce los siguientes tipos de valores:

  • Números
  • Valores booleanos

    true y false

  • Strings
  • Listas

    tipo de datos que asocia valores con un valor numérico poniendo el contenido de la lista entre corchetes, separando cada uno de los elementos mediante una coma

  • Tuplas

    tipo de datos que asocia valores con un valor numérico poniendo el contenido de la lista entre paréntesis, separando cada uno de los elementos mediante una coma

    Tienen la peculiaridad de ser inmutables

  • Diccionarios

    tipo de datos que asocia un valor a una clave y permite buscar por esas claves

  • Objetos

    Creados por el programador o predefinidos por el lenguaje

Al tratarse de un lenguaje con tipado dinámico, no es necesario decirle al intérprete su tipo de variable, sino que es él quien decide el tipo que asignará

Los nombres con los que podemos nombrar variables en Python siguen varias normas:

  • Los nombres empiezan siempre por letra
  • Dentro del nombre se puede usar cualquier letra o número dentro de la codificación utf-8
  • No se pueden usar las palabras reservadas de Python, que son usadas en su sintaxis de su código

    Para más información sobre estos nombres consultar en la documentación de Python

Notar que Python distingue entre mayúsculas y minúsculas, por lo que dos variables con el mismo nombre pero que contenga una letra en mayúscula serán entendidas como dos variables distintas

Por ejemplo Variable es diferente de variable

Además existen ciertos convenios para reducir errores y mejorar la legibilidad

Para evitar errores se recomienda no usar ciertos caracteres:

  • No usar ni l (ele minúscula) ni I (i mayuscula), ya que dependiendo del tipo de fuente que se use pueden confundirse entre si o con el número 1
  • No usar O (o mayúscula) ya que dependiendo del tipo de fuente que se use puede llevar a confusión con el número 0

A fin de favorecer la legibilidad se hacen las siguientes sugerencias:

  • nombredevarible es poco legible, por estar todo junto y puede dificultar su legibilidad
  • nombreDeVarible es un poco más legible, al aplicar letra mayúscula al iniciar palabra
  • nombre_de_variable es la que mejor legibilidad aporta, al aplicar guión bajo al iniciar palabra, que es la forma más recomendada

La sentencia if

La sentencia if tiene la forma:

En caso de que la condición sea verdadera se ejecutará la instrucción 1; en caso contrario se ejecuta si existe la instrucción 2

El uso de la sentencia else es opcional, por eso en la definición se han utilizado los corchetes

Si se omite, sólo se tendrá en cuenta el bloque de instrucciones cuando la condición sea verdadera

Un bloque de instrucciones es un conjunto de instrucciones tabulaciones después de la sentencia if, al saltar de línea después del símbolo :

Son obligatorias ya que le dicen al interprete que el bloque de instrucciones pertenece a la sentencia if

Si se omiten y la condición era verdadera, se ejecutará la siguiente instrucción

En caso contrario, se ejecutará la subsiguiente instrucción, de forma independiente al estado de la condición

De este modo, la omisión de las tabulaciones después de la sentencia if nos permitirá escribirlo todo en una única línea después del símbolo :

La sentencia elif

También podemos utilizar sentencias if anidades mediante la sentencia elif

Las sentencias elif funcionan igual que una sentencia if

Pero sólo se ejecutarán en caso de que la condición de la sentencia if fuese falsa

Podemos añadir opcionalmente una sentencia else al final pero sólo se ejecutará si todas las condiciones anteriores fuesen falsas

La sentencia while

La sentencia while tiene la forma

Si se cumple la condición, se ejecuta la instrucción o el bloque de instrucciones y se repite el proceso hasta que deje de cumplirse la condición

La sentencia for

Este bucle, tiene una sintaxis muy parecida al for-each de Java

Itera una variable var sobre todas las propiedades de un objeto obj que se le pasa

Así para cada valor de var se ejecutaran las sentencias del bucle

Por lo tanto, el bucle tendrá tantas iteraciones como propiedades el objeto y en cada iteración la variable tendrá el valor de la propiedad del objeto correspondiente con dicha iteración

Su sintaxis es:

Iteradores

En Python existen diferentes estructuras que son conjuntos de elementos, son las llamadas colecciones

Este tipo de estructuras son iterables, es decir, se pueden recorrer elemento por elemento

Algunos tipos de variable que son iterables son:

  • Cadena de caracteres (str)
  • Lista (list)
  • Tupla (tuple)
  • Diccionario (dict)

Su uso es útil para recorrer elementos de colección como las listas, las tuplas o los objetos

Además, muchas veces queremos repetir un bucle un número determinado de veces

Para esto puede ser útil la función range(n)

Esta función genera un iterable que va desde 0 hasta n – 1

La sentencia break

La sentencia break se puede colocar dentro de un bucle o bucles anidados

Cuando se ejecuta la sentencia break se abandona el bucle más interno

A todos los efectos la sentencia break actúa como un salto a la instrucción siguiente al bucle en el que se ejecuta

La sentencia continue

La sentencia continue, no abandona el bucle si no que hace que se ejecute la siguiente iteración

En el bucle while la ejecución del continue hace que el flujo del programa salte a la condición

En el bucle for la ejecución del continue hace que se ejecute la expresión de incremento, para después continuar normalmente con la condición

Es decir, la ejecución del continue evita que se ejecute el resto del cuerpo del bucle

Funciones en Python

Funciones en Python

Para definir funciones en Python disponemos de la instrucción def

Después de esta palabra reservada va el nombre de la función junto con una lista de argumentos delimitados por paréntesis y separados por comas, finalizando con el símbolo :

La definición de una función no ejecuta el cuerpo de la función

Solamente será ejecutada cuando la función sea llamada

Su ejecución enlaza el nombre de la función con el namespace local actual a un objecto función (un envoltorio alrededor del código ejecutable para la función)

Este objeto función contiene una referencia al namespace local global como el namespace global para ser usado cuando la función sea llamada

De forma opcional puede añadirse una expresión que será devuelta por la función

La expresión puede será un tipo válido de Python precedida por la sentencia return

El DOCSTRING es un texto descriptivo de la función encerrado entre tres comillas dobles de apertura y cierre, antes de la primera instrucción

Es opcional, así que si no queremos añadir una descripción, podemos omitirlo

Pero se recomienda su uso para que cuando revisemos después de un tiempo nuestro código, recordemos qué hacía nuestra función

Argumentos

El paso de argumentos es opcional y en algunos casos puede haber funciones que carezcan de ellos

Tipo de los argumentos

Admite los tipos str, int, float, complex,bool, list, tuple, dic y class

Argumentos con valor por posición

Cuando enviamos argumentos a una función, estos se reciben por orden en los parámetros definidos

Argumentos con valor por nombre

Es posible evadir el orden de los parámetros si indicamos durante la llamada el valor que tiene cada parámetro a partir de su nombre

Sin Argumentos

Al momento de llamar una función la cual tiene definidos unos parámetros, si no pasa los argumentos correctamente provocará una excepción TypeError

Argumentos con valor por defecto

En ocasiones necesitamos que un argumento tenga un valor, para evitar un error (que provocaría el lanzamiento de la excepción TypeError), aunque el usuario de la función no lo introduzca

Hay que tener en cuenta, que los argumentos con valor por defecto pasan a ser opcionales y que todos los argumentos a la izquierda del primer valor por defecto, son obligatorios

En el ejemplo se ha utilizado el valor nulo (None) para expresar que no se habían pasado argumentos

Pero podríamos utilizar cualquier tipo que precisemos como valor por defecto

Argumentos indeterminados

En algunas ocasiones no sabremos previamente cuantos elementos necesitamos enviar a una función

Para estos casos podemos utilizar los parámetros indeterminados por posición o por nombre

Argumentos por posición

Como argumento usaremos un tipo tuple precediendolo con el símbolo *

De esta forma todos los argumentos serán recibidos por posición, pudiendo recorrerlos cómodamente con un bucle for

Argumentos por nombre

Como argumento usaremos un tipo dict precediendolo con los símbolos **

De esta forma todos los argumentos serán recibidos por el nombre de la clave del diccionario, pudiendo recorrerlos cómodamente con un bucle for

Argumentos por posición y nombre

En alguna ocasión puede necesitar utilizar ambos tipos de parámetros simultáneamente en una función, entonces debe crear ambas colecciones dinámicas

Primero los argumentos indeterminados por valor y luego por nombre

En todos los ejemplos se han utilizado los nombres args y kwargs pero no son obligatorios

Muchos frameworks y librerías los utilizan por lo que es una buena practica llamarlos así, por convención

La sentencia pass

Es una operación nula, cuando la ejecutamos, parece que nada sucede

Es útil como un contenedor cuando una sentencia es requerida sintácticamente, pero no es necesario ejecutar código

La sentencia return

La sentencia return es la que permite devolver el resultado de una función

Admite los tipos str, int, float, complex,bool, list, tuple, dic y class

La setencia return es opcional, pero si se omite, por defecto devolverá el valor nulo (None)

Retorno múltiple

Una característica interesante de las funciones en Python, es la posibilidad de devolver valores múltiples separados por comas

Funciones predefinidas por el lenguaje

Las funciones predefinidas por el lenguaje están ordenadas por módulos

Un módulo es un conjunto de clases y funciones almacenadas en un archivo que pueden ser utilizadas posteriormente

Podemos crear nuestros propios módulos e importarlos a los nuevos programas que hagamos

Sin embargo, es aconsejable reutilizar los módulos ya existentes

Para importar un módulo utilizaremos la sentencia import

De esta forma estaremos manejando un namespace, de forma similar a como lo hace C++ (using namespaces) o Java

Que tiene la siguiente sintaxis

Para llamar a una función concreta del módulo utilizaremos nombre.funcion() o alias.funcion en caso de que le hayamos dado un alias al módulo

En caso de no querer utilizar todas la funciones del módulo pero si una concreta, utilizaremos la sentencia from

Que tiene la siguiente sintaxis

Módulo sys

Este módulo es el encargado de proveer variables y funcionalidades relacionadas con el intérprete

Las variables del módulo sys son:

  • sys.executable

    Retorna el directorio absoluto del archivo binario ejecutable del intérprete de Python

  • sys.platform

    Retorna la plataforma sobre la cual se está ejecutando el intérprete

  • sys.version

    Retorna el número de versión de Python con información adicional

Los métodos más destacados del módulo sys son los siguientes:

  • sys.exit()

    Forzar la salida del intérprete

  • sys.getdefaultencoding()

    Retorna la codificación de caracteres por defecto

  • sys.getfilesystemencoding()

    Retorna la codificación de caracteres que se utiliza para convertir los nombres de archivos unicode en nombres de archivos del sistema

  • sys.getsizeof()

    Retorna el tamaño del objeto pasado como parámetro

Módulo os

Este módulo nos permite acceder a funcionalidades dependientes del SO

Sobre todo, aquellas que nos dan información sobre el entorno del mismo y nos permiten manipular la estructura de directorios

Algunos de los métodos más utilizados son:

  • os.getcwd()

    Nos informa de cuál es el directorio actual

  • os.chdir(ruta)

    Cambia el directorio de trabajo a la ruta pasada como argumento

  • os.chroot()

    Cambia al directorio raiz

  • os.mkdir(directorio)

    Crea el directorio pasado como argumento

  • os.rmdir(directorio)

    Elimina el directorio pasado como argumento

  • os.remove(fichero)

    Eliminar el archivo pasado como argumento

  • os.rename(actual, nuevo)

    Renombra el archivo actual por el nombre del archivo nuevo, pasados como argumentos

Módulo math

Este módulo nos provee de funciones y constantes matemáticas

Podemos encontrar todas las funciones y atributos en su documentación

Algunas de los variables más utilizadas son:

  • math.pi

    Representa el valor de la variable \pi (número Pi)

  • math.e

    Representa el valor de la variable e (número de Euler o constante de Napier)

  • math.tau

    Representa el valor de la variable \tau = 2\cdot\pi (constante Tau, propuesta por Bob Palais, Peter Harremoes, Hermann Laurent, Fred Hoyle, Michael Hartl, Nicolás Atanes, entre otros)

Algunos de los métodos más utilizados son:

  • math.ceil(x)

    Devuelve el entero menor que sea mayor o igual que x

  • math.floor(x)

    Devuelve el entero mayor menor o igual a x

  • math.exp(x)

    Devuelve el número e elevado a la potencia x

  • math.log2(x)

    Devuelve el logaritmo en base 2 de x

  • math.sin(x)

    Devuelve el seno de x radianes

  • math.cos(x)

    Devuelve el coseno de x radianes

  • math.tan(x)

    Devuelve la tangente de x radianes

  • math.degrees(x)

    Convierte el ángulo x de radianes a grados

Módulo random

El módulo random se utiliza para todo lo relacionado con números aleatorios

Algunos de los métodos más utilizados son:

  • shuffle(col)

    Reordena aleatoriamente los elementos de una colección

  • sample(col, k)

    Toma n elementos sin reemplazo de una coleccion

  • random()

    Genera un número aleatorio en el intervalo [0, 1)

  • uniform(a, b)

    Genera un número aleatorio en el intervalo [a, b]

  • randint(a, b)

    Genera un número aleatorio entero en el intervalo [a, b]

  • gauss(media, sigma)

    Genera un número aleatorio siguiendo una distribución gaussiana con media y sigma dadas

Módulo NumPy

Numpy nos proporciona una gran cantidad de funciones matemáticas y el tipo de variable NumPy array

Por lo general el paquete NumPy suele importarse con el alias np

Este módulo nos permite trabajar con estructuras matemáticas de una forma muy cómoda (producto de matrices, números aleatorios, operaciones sobre matrices…)

Es un módulo que no viene instalado por defecto

Para ello abre un terminal y ejecuta:

Podemos encontrar todas las funciones y atributos en su documentación

Algunos de los métodos más utilizados son:

  • random.rand()

    Nos devuelve valores aleatorios con la forma deseada

  • empty()

    Crea un array vacío con la forma indicada

  • zeros()

    Crea un array de ceros con la forma indicada

  • dot()

    Calcula el producto matricial entre dos arrays

  • sum()

    Calcula la suma de los elementos de un array

Módulo Pandas

El paquete pandas es muy utilizado en el Data Scientists

Es uno de los paquetes sobre el que deberíamos centrarnos para aprender sobre análisis de datos

A través de pandas podemos familiarizarnos con nuestro set de datos limpiándolo, transformándolo y analizándolo

Por ejemplo, con pandas podemos leer un fichero CSV de nuestro ordenador, pasarlo a un DataFrame (una tabla, en esencia) y hacer cosas como:

  • Calcular estadísticas y responder preguntas sobre los datos como sacar el máximo, minimo y media de cada columna, saber cómo de correlacionadas están las columnas A y B o conocer la distribución estadística de la columna C
  • Limpiar los datos haciendo cosas como eliminar los valores faltantes o filtrando filas y columnas de acuerdo a algún criterio
  • Visualizar los datos con la ayuda de matplotlib
  • Guardar los datos ya limpiados de vuelta en un CSV o una base de datos
  • Pandas se basa en NumPy, por lo que debemos tener ese módulo instalado previamente

    Jupyter Notebooks es una aplicación que se complementa muy bien con Pandas, ya que podemos ejecutar el código por celdas en vez que de forma completa, lo cual es útil si trabajamos con grandes datasets

    Los componentes primarios de Pandas son series y DataFrame, siendo el primer tipo una columna y el segundo una table

    Por lo general el paquete pandas suele importarse con el alias np

    Es un módulo que no viene instalado por defecto

    Para ello abre un terminal y ejecuta:

    Podemos encontrar todas las funciones y atributos en su documentación

    Ahora vamos a crear un ejemplo sencillo para mostrar el uso de pandas usando una serie que contendrá a los integrantes de la selección Española de fútbol que ganó el mundial del año 2010

    Para crear la serie utilizamos el método pd.Series que recibirá una lista con los nombres de los jugadores y una lista con el número de dorsal de los jugadores

    Después lo mostraremos por pantalla

    Ahora no le vamos a indicar los índices de forma explícita, entonces generará los índices de forma automática empezando desde el valor cero

    Ahora vamos a introducir en la serie un diccionario en vez de una lista y le vamos a añadir un jugador más

    Ahora vamos a crear un ejemplo sencillo para mostrar el uso de pandas usando un DataFrame que contendrá a los integrantes de la selección Española de fútbol que ganó el mundial del año 2010

    Para crear el DataFrame utilizamos el método pd.DataFrame que recibirá un diccionario con los datos de los jugadores, una lista con el nombre de la columna y una lista con el número de dorsal de los jugadores

    Añadiremos un jugador más utilizando el método loc del objeto DataFrame

    Después lo mostraremos por pantalla

    Funciones de visualización

    print

    La función print sirve para enviar la salida de sus argumentos al navegador con un formato

    Operador %

    El operador % también se puede utilizar para el formato de la cadena

    Interpreta el argumento izquierdo de manera muy parecida a una cadena de formato de estilo de la función printf de C++, que se aplica al argumento derecho

    En Python, no hay una función printf pero se le ha dotado de su funcionalidad a print

    Para este propósito, el operador % está sobrecargado para cadenas para mostrar el formato de la cadena

    A menudo se le llama operador de módulo de cadena (o, a veces, incluso, módulo)

    Tiene el formato:

    Para formatear un texto deberemos introducir los siguientes caracteres de formato precedidos por el símbolo %:

    Caracteres de formato para texto
    Caracter Descripción
    c

    El argumento es tratado como un valor de tipo string y recoge un único carácter

    d

    El argumento es tratado como un valor de tipo int y presentado como un número entero

    e

    El argumento es tratado con notación científica (por ejemplo 1.2e+2)

    E

    Como %e pero utiliza la letra mayúscula (por ejemplo 1.2E+2)

    f

    El argumento es tratado como un valor de tipo float y presentado como un número de punto flotante (considerando la configuración regional)

    F

    El argumento es tratado como un valor de tipo float y presentado como un número de punto flotante (sin considerar la configuración regional)

    g

    Igual que %e y %f

    G

    Igual que %E y %f

    o

    El argumento es tratado como un valor de tipo integer y presentado como un número octal

    s

    El argumento es tratado como un valor de tipo string y recoge una cadena de caracteres

    u

    El argumento es tratado como un valor de tipo int y presentado como un número decimal sin signo

    x

    El argumento es tratado como un valor de tipo integer y presentado como un número hexadecimal

    X

    El argumento es tratado como un valor de tipo integer y presentado como un número hexadecimal en mayúsculas

    Método format

    El método format se añadió a los tipos string en Python 2.6

    Permite el uso de los caracteres {} para marcar dónde se sustituirá una variable y utiliza directivas de formato detalladas usadas para formatear

    Este método nos permite concatenar elementos dentro de una salida a través del formato posicional

    Los corchetes y los caracteres dentro de ellos (llamados campos de formato) se reemplazan con los objetos pasados al método format

    Se puede usar un número entre paréntesis para referirse a la posición del argumento pasado al método format

    Hay que tener en cuenta que el primer argumento empieza en cero

    También se puede usar un identificador clave cuando el argumento sea pasado por nombre

    Esta opción nos será útil cuando trabajemos con diccionarios o cuando queramos reducir algo el código

    Opcionalmente se puede poner el símbolo : después del número o nombre, y explicitar el tipo del objeto:

    Caracteres de formato para texto
    Caracter Descripción
    s

    El argumento es tratado como un valor de tipo string y recoge una cadena de caracteres

    d

    El argumento es tratado como un valor de tipo int y presentado como un número decimal (con signo)

    f

    El argumento es tratado como un valor de tipo float y presentado como un número de punto flotante (considerando la configuración regional)

    Funciones de orden superior

    En matemáticas y ciencias de la computación, las funciones de orden superior son funciones que cumplen al menos una de las siguientes condiciones:

    • Tomar una o más funciones como entrada
    • Devolver una función como salida

    Funciones lambda

    Las funciones lambda son funciones anónimas, es decir, funciones sin nombre

    Sólo se utilizan en el lugar en el que se han creado (aunque se les puede asignar un nombre y usarlas más adelante)

    Se utilizan por lo general junto a las funciones map, filter y reduce

    Por lo general se utilizan para crear funciones que son pasadas como argumentos a otras funciones

    En Python la sintaxis de una función lamdba es:

    Donde la expresión puede ser cualquier operación que haríamos al realizar una asignación

    Funcion map

    Nos permite aplicar una función sobre cada uno de los elementos de un iterable

    Nos devuelve un map object, que podemos transformar fácilmente en una lista

    Funcion filter

    Nos permite filtrar los elementos de una colección (por ejemplo una lista)

    Es una función muy utilizada en el tratamiento de colecciones

    Función reduce

    Toma una función y una colección reduciéndola a un solo valor

    Sería equivalente a una función de agregación

    Pertenece al módulo functools, por lo que deberá ser importado antes de poder usar reduce

    La función que pasemos debe tomar al menos dos parámetros y uno opcional

    El primero es el parámetro del agregado que se va acumulado en cada iteración sobre los elementos de la colección

    El segundo el elemento corresponde al paso de la iteración

    El tercero es en caso que se necesite un valor inicial

Excepciones en Python

Excepciones en Python

Si una operación no puede completarse debido a un error, el programa deberá:

  • volver a un estado estable y permitir otras operaciones

  • intentar guardar el trabajo y finalizar

Esta tarea es difícil debido a que generalmente el código que detecta el error no es el que puede realizar dichas tareas por eso debe informar al que pueda manejarlo

La solución más habitual son los códigos de error

Python ofrece otra forma de tratar con los errores en condiciones excepcionales: las excepciones

Una condición excepcional es aquella que impide la continuación de una operación

No se sabe como manejarla, pero no se puede continuar

En Python se lanza una excepción para que alguien que sepa manejarla la trate en un contexto superior

En el ejemplo la función open comprueba si el fichero readme.txt existía en el sistema y en caso de no existir se lanza la excepción FileNotFoundError que de momento está sin tratar

Cuando el intérprete detecta el lanzamiento de la excepción finaliza el método actual y lanza un objeto que facilite información sobre el error ocurrido

Normalmente se gestionará cada tipo de error de forma individual

Manejo de la excepciones

Una vez detectado el error hace falta indicar quien se encarga de tratarlo

Un manejador de excepciones tiene el siguiente formato:

Bloque try

El bloque try delimita el grupo de operaciones que puede producir excepciones

Bloque except

El bloque except es el lugar al que se transfiere el control si alguna de las operaciones produce una excepción

En el ejemplo se ha usado un bloque try con su bloque except para gestionar los errores del ejemplo anterior

Si alguna de las operaciones del bloque produce una excepción, se interrumpe el bloque try y se ejecuta el except

Al finalizar este, se continua normalmente

Si no se produce ninguna excepción, el bloque except se ignora

Excepciones múltiples

También existe la posibilidad de utilizar un nombre de excepción para tratar errores específicos

Algunos de los cuales ya son reconocidos por el sistema, como la excepción FileNotFoundError, que se lanza cuando un archivo no existe en el sistema

En el ejemplo se ha usado un bloque try con varios bloques except para gestionar varias excepciones

Un bloque try puede tener varios except asociados

Le hemos añadimos la sentencia as al bloque except despues de nombrarlo para convertirlo en el objeto de excepción que hemos llamado e

Como puede verse, después de convertirlo en objeto, podemos utilizarlo como si fuera una clase

Cuando una excepción no se corresponde con ningún catch se propaga hacia atrás en la secuencia de invocaciones hasta encontrar un catch adecuado

En el ejemplo se gestionan las excepciones de los métodos f1 y f2 y si no encuentran ninguna continua la ejecución del código de forma normal fuera del bloque try

Se ha usado la sentencia raise seguida del nombre del tipo de excepción para propagarla y tratarla en otro lugar

En este caso la hemos tratado dentro de la propia función f1 en sus bloques excepción

Aunque al propagarla podría haberse tratado fuera de la misma en otro lugar del script

También se ha utilizado un bloque else que permite continuar la ejecución del código en caso de que no haya excepciones antes de continuar fuera del bloque try

Bloque else

Permite continuar la ejecución del código en caso de que no haya excepciones antes de continuar fuera del bloque try

El bloque else puede utilizarse para salir de un bucle si al final del mismo se añade la sentencia break

Es opcional y si no se usa, continuará la ejecución del código en el bloque finally y por último fuera del bloque try

Bloque finally

Puede haber ocasiones en que se desea realizar alguna operación tanto si se producen excepciones como si no

Dichas operaciones se pueden situar dentro de un bloque finally

Si no hay ninguna excepción se ejecutará el bloque try, después el bloque else y por último el finally

Al igual que el bloque else, es opcional y si no se usa, continuará la ejecución del código fuera del bloque try

Normas de uso

  1. Norma

    • Si una excepción se puede manejar no debe propagarse

    • Es más cómodo usar métodos que no produzcan errores

  2. Norma

    • No utilizar las excepciones para evitar una consulta

      • No abusar de ellas

  3. Norma

    • Separar el tratamiento de errores de la lógica

      Todo junto
      Separado
  4. Norma

    • No ignorar una excepción ya que dejamos el código con errores sin controlar

Página Web

Página web

Una página web, o página electrónica, página digital, o ciberpágina es un documento o información electrónica capaz de contener texto, sonido, vídeo, imágenes digitales, programas, acceso a otras páginas web mediante enlaces de hipertexto, imágenes, etc

Se difunde en los formatos HTML o XHTML, también incluye otros recursos llamados hojas de estilo en cascada (CSS) y guiones (scripts)

Una página web puede estar almacenadas en un equipo local o en un servidor web remoto

Un servidor web puede restringir el acceso únicamente a redes privadas, por ejemplo, una intranet corporativa, o puede publicar las páginas en la World Wide Web (WWW)

El acceso a las páginas web es realizado mediante una transferencia desde servidores, utilizando el protocolo de transferencia de hipertexto (HTTP) o el protocolo de transferencia de hipertexto seguro (HTTPS), siendo accesible desde un navegador

Html

Html

El lenguaje HTML (hypertext markup language) describe el contenido de una página web, incluyendo el texto, las imágenes, los vídeos, etc

Las especificaciones sobre el funcionamiento de la web las hace el W3C (World Wide Web Consortium). En su página web podemos encontrar toda la documentación sobre HTML y otros estándares de la red

Para la edición de páginas web podemos usar cualquier editor de texto

En windows el Bloc de notas o el Wordpad, en linux vi, joe, mcedit, etc

En ellos aprovecharemos las capacidades de cada uno de copiar y pegar. Existen multitud de editores web que nos facilitan la inserción de código HTML

Unos freeware, otros shareware y otros comerciales como Adobe Dreamweaver con el que se obtienen unas páginas más profesionales ya que cuentan con plantillas predefinidas que agilizan nuestra labor

Para desarrolladores avanzados tenemos Sublime Text, aunque puede ser poco amigable para el resto de desarrolladores

Entre los más amigables tenemos Brackets, que permite visualizar el código HTML automáticamente

Y Atom, como otra alternativa más, que ahora se está poniendo de moda

Hay que tener muy en cuenta el tipo de codificación que usemos con este lenguaje, ya que si al escribir nuestra página web usamos una codificación distinta a la del navegador web, podemos obtener una página con caracteres extraños o ilegibles

La opción más usada es la codificación UTF-8, que es el estándar para Internet y para sistemas Linux

Los sistemas Windows y MacOS utilizan otros tipos de codificación por lo que deberemos hacer coincidir la codificación en la cabecera del documento, con la que será mostrada en el navegador web

Estándares

HTML 1.0

Tim Berners-Lee en 1991 describe 18 elementos que incluyen el diseño inicial y relativamente simple de HTML. Trece de estos elementos todavía existen en HTML 4.4

Berners-Lee consideraba el HTML una ampliación de SGML, pero no fue formalmente reconocida como tal hasta la publicación a mediados de 1993, por el IETF (Internet Engineering Task Force), de una primera proposición para una especificación del HTML: el borrador del Hypertext Markup Language de Berners-Lee y Dan Connolly, que incluía una Definición de Tipo de Documento SGML para definir la gramática

El borrador expiró a los seis meses, pero fue notable por su reconocimiento de la etiqueta propia del navegador Mosaic usada para insertar imágenes sin cambio de línea, que reflejaba la filosofía del IETF de basar estándares en prototipos con éxito. De la misma manera, el borrador competidor de Dave Raggett HTML+ (Hypertext Markup Format), de finales de 1993, sugería estandarizar características ya implementadas, como las tablas

HTML 2.0

La versión oficial para HTML fue hasta hace pocos años la HTML 2.0, denominado HTML+, comenzó a desarrollarse a finales de 1993. Se diseñó originalmente para ser un superconjunto del HTML que permitiera evolucionar gradualmente desde el formato HTML anterior

A la primera especificación formal de HTML+ se le dio, por lo tanto, el número de versión 2.0 para distinguirla de las propuestas no oficiales previas. Los trabajos sobre HTML+ continuaron, pero nunca se convirtió en un estándar, a pesar de ser la base formalmente más parecida al aspecto compositivo de las especificaciones actuales

Cumplía su función perfectamente, pero muchos usuarios del HTML querían tener un control mayor sobre sus documentos, tanto en el formateo del texto como en la apariencia de la página

HTML 3.0

Mientras tanto, Netscape, que era en esa época el líder indiscutible de los navegadores, introducía con cada nueva versión etiquetas y atributos no contemplados en el estándar oficial, creando descontento entre algunos desarrolladores

Debido a su amplia difusión y aceptación, otros navegadores intentaban copiar esas innovaciones, pero debido a que Netscape no especificaba completamente sus nuevas etiquetas, los resultados no eran distintos de los deseados. Lo que provocaba una gran confusión y numerosos problemas, cuando los desarrolladores utilizaban estos elementos y comprobaban que no funcionaba como querían en otros navegadores

El borrador del estándar HTML 3.0 fue propuesto por el recién formado W3C en marzo de 1995. Con él se introdujeron muchas nuevas capacidades; por ejemplo, facilidades para crear tablas, hacer que el texto fluyese alrededor de las figuras y mostrar elementos matemáticos complejos. Aunque se diseñó para ser compatible con HTML 2.0, era demasiado complejo para ser implementado con la tecnología de la época, y cuando el borrador del estándar expiró en septiembre de 1995, se abandonó debido a la carencia de apoyos de los fabricantes de navegadores web

HTML 3.2

El HTML 3.1 nunca llegó a ser propuesto oficialmente, y el estándar siguiente fue el HTML 3.2, que abandonaba la mayoría de las nuevas características del HTML 3.0 y, a cambio, adoptaba muchos elementos desarrollados inicialmente por los navegadores web Netscape y Mosaic. La posibilidad de trabajar con fórmulas matemáticas que se había propuesto en el HTML 3.0 pasó a quedar integrada en un estándar distinto llamado MathML

Cada vez era más evidente la necesidad de un nuevo estándar que fuera aceptado por todos. Se formó otro comité, el W3C, apoyado por los principales vendedores de software (entre ellos, IBM, Microsoft, Novell, Netscape, Sun, etc). El nuevo estándar fue desarrollado durante todo el año 1996 por el W3C con el sobrenombre de Wilbur, y finalmente, en Enero de 1997 fue aprobado como el HTML 3.2

El HTML 3.2 era totalmente compatible con el estándar anterior, pero incorpora muchas de las innovaciones de los navegadores comerciales (Netscape e Internet Explorer principalmente), tales como tablas, applets, texto que bordea las imágenes, entre otras, aunque no todas, como por ejemplo los frames

HTML 4.0

En Julio de 1997 se presentó el primer borrador público del estándar oficial HTML 4.0 (que tiene el nombre clave de Cougar). En él se incorporan las especificaciones sobre tablas, frames, scripts, hojas de estilo, accesibilidad por distintos medios, e internacionalización (incluyendo el uso de Unicode, en lugar del Latin-1)

En 1997, HTML 4.0 (que tiene el nombre clave de Cougar) se publicó como una recomendación del W3C. HTML 4.0 adoptó muchos elementos específicos desarrollados inicialmente para un navegador web concreto, pero al mismo tiempo comenzó a limpiar el HTML señalando algunos de ellos como deprecated (desaprobados)

HTML 4.0 implementa características como XForms 1.0 que no necesitan implementar motores de navegación que eran incompatibles con algunas páginas web HTML. En él se incorporan las especificaciones sobre tablas, frames, scripts, hojas de estilo, accesibilidad por distintos medios, e internacionalización (incluyendo el uso de Unicode, en lugar del Latin-1)

HTML 5.0

HTML5 especifica dos variantes de sintaxis para HTML: una «clásica», HTML (text/html), conocida como HTML5, y una variante XHTML conocida como sintaxis XHTML5 que deberá servirse con sintaxis XML (application/xhtml+xml). Esta es la primera vez que HTML y XHTML se han desarrollado en paralelo

En 2004 la W3C reabrió el debate de la evolución del HTML, y se dieron a conocer las bases para la versión HTML5. No obstante, este trabajo fue rechazado por los miembros del W3C y se daría preferencia al desarrollo del XML

Apple, Mozilla y Opera anunciaron su interés en seguir trabajando en el proyecto bajo el nombre de WHATWG, que se basa en la compatibilidad con tecnologías anteriores

En 2006, el W3C se interesó en el desarrollo de HTML5, y en 2007 se unió al grupo de trabajo del WHATWG para unificar el proyecto

La versión definitiva de la quinta revisión del estándar se publicó en octubre de 2014

Al no ser reconocido en viejas versiones de navegadores por sus nuevas etiquetas, se recomienda al usuario común actualizar su navegador a la versión más nueva, para poder disfrutar de todo el potencial que provee HTML5

Formato de una página Html

Formato de una página HTML

Su principio esencial es el uso de etiquetas (tags). Las etiquetas son palabras reservadas del lenguaje encerradas entre < >

Tipos de etiquetas

Hay tres tipos de etiquetas:

  • Pareadas
    cuando aparece una etiqueta de inicio y otra de final, los bloques contenidos entre el inicio y el cierre son elementos, que su vez pueden contener otros elementos

  • Sin parear
    cuando la etiqueta representa la inserción de un elemento, estas etiquetas terminan con una barra inclinada

  • Con final opcional
    son etiquetas pareadas en la cuales no es obligatorio emplear la etiqueta final

Las etiquetas pueden incluir atributos que modifican su comportamiento, especificando alguna característica singular del elemento o incluyendo información adicional

Los atributos se especifican como pares atributo=’valor’, separados por espacios dentro de la etiqueta de inicio

No es obligatorio que los valores estén encerrados entre comillas, pero sí es recomendable

Pueden utilizarse comillas simples o dobles indistintamente, siempre que coincidan su apertura y cierre

En el ejemplo se ha utilizado el atributo id, el cuál es genérico para cualquier etiqueta y que nos será de utilidad cuando usemos CSS y Javascript, ya que nos permite distinguir de forma única el elemento al que pertenece esa etiqueta concreta

Existen más atributos genéricos, como por ejemplo class, title o style, todos ellos muy útiles cuando queramos dar formato o mejorar la accesibilidad a nuestros elementos

Cuando introducimos una etiqueta que no existe, esta será ignorada, debemos prestar atención a este asunto porque dificulta la detección de errores

Las etiquetas pueden escribirse en mayúsculas o en minúsculas

No se consideran los saltos de línea ni los espacios en blanco extras. Esto último permite indentar el código para hacerlo más legible

Comentarios dentro del HTML

A veces es muy útil escribir comentarios en el documento HTML sobre el código que escribimos, nos pueden servir para recordar posteriormente lo que fue hecho, y que no queremos que se vea en pantalla

Esto se consigue encerrando dichos comentarios entre estos dos símbolos:

Los comentarios se pueden utilizar en cualquier parte del documento HTML, pero no se verá en pantalla

Caracteres especiales

Hay ciertos caracteres que un navegador no es capaz de reconocer a pesar de utilizar la codificación correcta

Imaginemos que queremos escribir el texto x > y dentro de nuestro HTML, sin embargo, el carácter > no será reconocido por el navegador o nos mostrará uno erróneo

Esto ocurre con un conjunto de caracteres que son especiales y que el navegador reconocerá utilizando la etiqueta específica de ese carácter con el siguiente formato &etiqueta;

En el ejemplo anterior, la etiqueta para el carácter > es gt, empezando por & y terminando por ;

En la siguiente web podremos consultar la lista completa de los 256 caracteres universales HTML