Python 3 desde cero
Descubre el fascinante mundo del lenguaje de programación que funciona como una auténtica navaja suiza cuando se trata...
En este artículo te hablamos sobre las características de Python, aquellas que hacen que sea uno de los lenguajes más utilizados y valorados por la comunidad.
Hoy en día son muchos los desarrolladores que utilizan el lenguaje de programación Python para realizar tareas de diversa índole en campos tan distintos como el desarrollo web o el procesado de grandes volúmenes de datos. Esto está motivado por la gran cantidad de librerías, la facilidad de aprendizaje y la velocidad a la hora de crear prototipos frente a otros lenguajes.
Python es un lenguaje de programación interpretado, multiparadigma y multiplataforma que fue creado por el ingeniero Guido Van Rossum a finales de los ochenta con el objetivo, en aquel momento, de ser un fuerte sucesor del lenguaje de programación ABC, una alternativa al lenguaje BASIC que estaba orientada a crear prototipos rápidos.
Muchos adeptos del lenguaje mencionan que, a diferencia de otros, Python es sencillo y flexible gracias a la visión exclusiva de su creador a la hora de introducir nuevas mejoras y el hecho de basarse principalmente en el cumplimiento de unas veinte sencillas reglas que su autor denomina como “Zen de Python”, algunas de estas son:
Aunque si deseas saber más sobre el lenguaje, mi compañero lo explica en mayor profundidad en su artículo Qué es Python.
Python se caracteriza principalmente como lenguaje por su sintaxis simple y expresiva, cuyo objetivo principal es aumentar la legibilidad y la facilidad de desarrollo. Veamos algunos ejemplos representativos de su sintaxis a través de métodos, funciones y tareas habituales durante el desarrollo.
En el caso de la presentación por pantalla se opta en Python 3 por el uso de la función print
, de forma que un simple programa “hola mundo” podría escribirse así:
print('¡Hola Mundo!')
Esta función tiene además soporte para imprimir varias cadenas e incluso estructuras de datos complejas como tuplas o listas:
# En el caso de una tupla
x = ('Una cadena', 'Otra cadena', 'Otra más')
print(x)
Y esto nos imprimirá por consola ('Una cadena', 'otra cadena', 'otra más')
.
En Python una lista es un tipo de dato y es una de las cuatro estructuras de datos nativas, siendo las otras las tuplas, diccionarios y conjuntos, que nos permite agrupar un conjunto de valores no necesariamente del mismo tipo, de forma que pueden albergar simultáneamente cadenas, enteros, booleanos…etc. Un ejemplo de lista en Python sería:
my_list = ['Un item', 354, 'Otro item', True]
Al igual que los arrays y listas de otros lenguajes, las listas en Python también tienen una serie de métodos básicos en su uso cotidiano. Por ejemplo y para la lista anterior:
print(my_list[1]) # Esto devolverá el entero 354
print(my_list[1:3]) # Esto devuelve la sub-lista [354, 'Otro item']
len(my_list) # Este método devuelve la longitud de la lista, 4 en este caso
my_list.append(56) # Añade el valor 56 al final de la lista
print(my_list) # Imprime ['Un item', 354, 'Otro item', True, 56]
my_list.pop(1) # Elimina el valor en la posición 1
print(my_list) # Imprime ['Un item','Otro item', True, 56]
other_list = my_list.copy() # Copia la lista my_list en otra variable
Estos métodos, además de otros para tareas más concretas, no son sin embargo la razón de la potencia de las listas en Python, sino la llamada comprensión de listas, un proceso para crear de manera concisa nuevas listas de una manera rápida y eficiente. Primero, y sin usar comprensión de listas, veamos un ejemplo en el que creamos una lista que almacene los diez primeros múltiplos de tres:
multiples = []
for x in range(10):
multiples.append(x * 3)
print(multiples)
# Esto imprime [0, 3, 6, 9, 12, 15, 18, 21, 24, 27]
Ahora, realizando este mismo proceso pero usando ahora comprensión de listas:
multiples = [x * 3 for x in range(10)]
print(multiples)
# Esto imprime [0, 3, 6, 9, 12, 15, 18, 21, 24, 27]
Podemos observar como es equivalente. Y su potencia no acaba en listas sencillas como estas, es capaz de crear estructuras complejas anidadas utilizando iteradores y condiciones. Como por ejemplo esta comprensión de listas:
combs = [(x, y) for x in [1,2,3] for y in [3,1,4] if x != y]
que es equivalente a:
combs = []
for x in [1,2,3]:
for y in [3,1,4]:
if x != y:
combs.append((x, y))
Y ambas realizan el mismo proceso combinando los elementos de dos listas en tuplas si estos no son iguales, produciendo la lista combs = [(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]
.
Otra de las grandes características que definen a Python por su sencillez y flexibilidad es la manipulación de cadenas.
Esta característica se debe, en gran parte, a que en python una cadena de longitud superior a uno se considera como un array de cadenas de longitud uno, es decir, en Python internamente la cadena 'hola'
es considerada como ['h','o','l','a']
. Esto es una diferencia importante respecto a otros lenguajes donde las cadenas se consideran arrays de elementos de tipo char
y no de tipo string
.
Esto que puede resultar a priori tan poco interesante ofrece, sin embargo, un gran abanico de posibilidades, ya que al considerar una cadena como un grupo de cadenas podemos utilizar métodos y notaciones similares a las listas:
a = '¡Hola Mundo!'
print(a[1]) # Esto imprimirá el caracter en la segunda posición como cadena, es decir 'H'
print(a[1:5]) # Al igual que en una lista esto nos devuelve la sub-cadena 'Hola'
print(a[-5:-2]) # Partiendo desde el final esto nos devuelve la sub-cadena 'und'
print(len(a)) # Imprime la longitud de la cadena, en este caso 12
También, por supuesto, las cadenas tienen una serie de métodos básicos orientados al procesamiento del texto como capitalize()
que transforma el primer caracter de una cadena en mayúscula o lower()
que convierte toda la cadena en minúsculas.
Aunque fueraparte de los métodos habituales que podemos encontrar con frecuencia en otros lenguajes, quizás sea format()
uno de los métodos más prácticos, ya que como Python no nos deja combinar tipos (No podemos concatenar un número a una cadena) nos permite crear cadenas “plantilla” en las que inyectar otros valores, por ejemplo:
plantilla = 'Hola, me llamo {0} y tengo {1} años'
print(plantilla.format('Pablo', 30))
# Esto imprimirá 'Hola me llamo Pablo y tengo 30 años'
print(plantilla.format('Manuel', 28))
# Esto imprimirá 'Hola me llamo Manuel y tengo 28 años'
Aparte de los métodos y funciones vistos anteriormente para realizar tareas habituales en el día a día, Python posee una colección más extensa orientada a facilitar ciertas tareas no tan habituales pero que suelen requerir de soluciones que a veces tienden a disminuir la legibilidad de nuestro código. A continuación te mostramos algunas.
En ocasiones tenemos unas cuantas listas y nos encontramos en la tesitura de necesitar unirlas en una sola respetando el orden de aparición por miembro. Es decir, para unas listas year = [2010, 2012, 2015]
, month = ['Aug', 'Jun', 'Sept']
y day = [4, 23, 15]
aplicando una cierta función zip(year, month, day)
obtener una lista completa de tuplas ordenadas [(2010, 'Aug', 4), (2012, 'Jun', 23), (2015, 'Sept', 15)]
.
Aunque esto no es una tarea compleja suele requerir de una estructura de código un poco enrevesada, por ejemplo una implementación posible de esta función en Javascript sería:
function zip() {
for (var i = 0; i < arguments.length; i++) {
if (!arguments[i].length || !arguments.toString()) {
return false;
}
if (i >= 1) {
if (arguments[i].length !== arguments[i - 1].length) {
return false;
}
}
}
var zipped = [];
for (var j = 0; j < arguments[0].length; j++) {
var toBeZipped = [];
for (var k = 0; k < arguments.length; k++) {
toBeZipped.push(arguments[k][j]);
}
zipped.push(toBeZipped);
}
return zipped;
}
Sin embargo en Python ya se dispone de esta función y de su forma inversa, de forma que:
year = [2010, 2012, 2015]
month = ['Aug', 'Jun', 'Sept']
day = [4, 23, 15]
zipped = zip(year, month, day)
# Esto devuelve [(2010, 'Aug', 4), (2012, 'Jun', 23), (2015, 'Sept', 15)]
unzYear, unzMonth, unzDay = zip(*zipped)
# Esto devuelve cada lista original en las nuevas variables definidas
Esta función tiene aplicaciones avanzadas interesantes, como a la hora de realizar operaciones con matrices matemáticas, ya que zip()
puede utilizarse en su forma inversa junto a comprensiones de listas para calcular con facilidad la matriz traspuesta de una matriz dada:
matrix = [[1,3,4], [2,5,10]]
trans_matrix = [list(row) for row in zip(*matrix)]
print(trans_matrix) # Imprime la traspuesta [[1, 2], [3, 5], [4, 10]]
En ocasiones necesitamos un control fino del consumo interno en memoria de las variables que manejamos, para así asegurarnos que no vayamos a desbordar la memoria disponible. Para ello Python provee un método en sys
, uno de sus módulos nativos, para calcular el tamaño en bytes que está ocupando cierta variable en memoria proporcionada como argumento:
import sys
var_1, var_2, var_3, var_4 = "prueba", "te", 5, 20.10
print(sys.getsizeof(var_1)) # Imprime 38
print(sys.getsizeof(var_2)) # Imprime 35
print(sys.getsizeof(var_3)) # Imprime 24
print(sys.getsizeof(var_4)) # Imprime 24
Como curiosidad podemos observar que, en el caso de cadenas de distinta longitud, el peso en bytes es distinto ya que su asignación de memoria es dinámica.
Al igual que utilizábamos el método format
en cadenas para usarlas a modo de “plantillas” rellenables, es interesante hacer notas que las cadenas también poseen un método más avanzado para aplicar este mismo principio a diccionarios, el método format_map
:
data = {'name': 'Pablo', 'age': 30, 'sport': 'fútbol', 'drink': 'fanta'}
print('¡Hola! Me llamo {name} y me encanta el {sport} y beber {drink}'.format_map(data))
# Esto imprime "¡Hola! Me llamo Pablo y me encanta el fútbol y beber fanta"
Una de las fortalezas evidentes de esté método es la capacidad de transformar y visualizar rápidamente datos llegados en forma de diccionarios, lo cual es generalmente el día a día de todo desarrollador que trabaje con APIs REST.
Las variables mágicas, llamadas por convenio *args
y **kwargs
, son una forma de pasar un número indeterminado de parámetros a una función, pese a su nombre realmente se utilizan los operadores *
y **
, y las diferencias entre ambas son sutiles. Sea la función:
def test_magic_vars(var1, var2, var3):
print('var1: {0}, var2: {1}, var3: {2}'.format(var1, var2, var3))
Variables *args - Este caso se utiliza cuando los parámetros que vamos a mandar o definir en una función no tienen nombre, es decir, se encuentran simplemente ordenados en valor. En el caso de la función anterior podemos llamar a la función así:
params = (0,25,3)
test_magic_vars(*params) # Esto imprime 'var1: 0, var2: 25, var3: 3'
También podemos definir una función cuyos argumentos sean *args
de forma que dejamos claro que tratamos un número indeterminado de parámetros sin nombre en dicha función, por ejemplo:
def print_my_vars(*my_args):
for var in my_args:
print(var)
print_my_vars(34,56,78,38) # Esto imprime los argumentos 34 56 78 38
Variables **kwargs - Este caso es similar al anterior pero para parámetros con nombre, es decir, parámetros que se encuentren en forma de diccionarios y tengan por tanto clave-valor. En el caso de la función anterior podemos llamarla ahora:
params = {"var2": 25, "var3": 3, "var1": 0}
test_magic_vars(**params) # Esto imprime 'var1: 0, var2: 25, var3: 3'
Y podemos definir también una función con un número de argumentos indeterminado pero ahora contando con que dichos parámetros tienen cierto nombre:
def print_my_vars(**my_args):
for key, val in my_args:
print('{0} = {1}'.format(key, val))
print_my_vars({'my_var': 30, 'lulu': 'hi'}) # Esto imprime 'my_var = 30' y 'lulu = hi'
En muchas ocasiones y para todo desarrollador novato surge en algún momento la duda: “¿Qué lenguaje es más rápido?”, y la respuesta es, y ha sido siempre, invariablemente la misma: Depende.
Y esto es debido a que quizás un lenguaje interpretado como Python no sea tan rápido como C o C++ a la hora de ejecutarse, y es casi seguro que nunca alcance tal rendimiento al ejecutar (A pesar de ciertas librerías del lenguaje que ya utiliza compiladas directamente en C), pero sin duda Python es uno de los lenguajes en los que es más rápido desarrollar, y en muchas ocasiones, cuando los recursos no son un problema, esta es la pieza clave a la hora de elegir un stack tecnológico.
Pero no es necesario que se acepte esto como dogma, pongamos un ejemplo comparativo con otro lenguaje interpretado muy popular: Java. Veamos un sencillo ejemplo en Java en el que abrimos un archivo y añadimos cada línea a un array:
List<String> getRecords(String filename) throws IOException {
List<String> result = new ArrayList<>();
try (BufferedReader reader = new BufferedReader(new FileReader(filename))) {
String line;
while ((line = reader.readLine()) != null) {
result.add(line);
}
}
return records;
}
Y este mismo ejemplo escrito ahora en Python:
def get_records(file_name):
with open(fname, 'r') as fp:
return fp.read().split('\n')
Como podemos observar la simplicidad del código Python y su legibilidad potencian claramente la capacidad del lenguaje para escribir más rápido funcionalidades que en otros lenguajes populares, como en este caso Java.
Como hemos visto en este pequeño recorrido por Python, su sintaxis y sus pequeños trucos, nos encontramos ante un lenguaje que nos permite una gran velocidad de prototipado, una tremenda flexibilidad y produce un código limpio, ordenado y muy legible.
No por nada este lenguaje ha experimentado un crecimiento meteórico en su uso desde su creación hace ya más de 30 años, hasta el punto de estar considerado actualmente el lenguaje más popular del momento, seguido por otros titanes como son Java, Javascript o C#. Además, la creación de librerías y módulos especializados por la comunidad como lo son librosa (Para procesamiento de audio), sklearn (Para machine-learning) o frameworks como Django (Para desarrollar soluciones webs basadas en Python) amplían enormemente sus capacidades y extienden su popularidad hacia muchos campos populares del desarrollo profesional.
Y hasta aquí todo por ahora, espero que este artículo haya servido como una buena introducción para todo aquel desarrollador por vocación, y si quieres aprender más sobre el lenguajes no dudes en echarle un ojo a nuestro curso de Python desde cero.
También te puede interesar
Descubre el fascinante mundo del lenguaje de programación que funciona como una auténtica navaja suiza cuando se trata...
Aprende a crear un sitio web con Flask, el mini framework web de Python, perfecto para aquellos que...