Buscar este blog

lunes, 8 de abril de 2024

Las Funciones Incorporadas de Python



Bajo el capó de Python encontramos la Biblioteca Estándar, un conjunto de gran cantidad de funciones que se incluyen con el lenguaje. Generalmente vienen en módulos que se vinculan a nuestro programa con la sentencia import. Un simple import, y ya podemos usarlas. Y son nativas, aquí no interviene ningún fabricante ni autor ajeno a Python. Las tenemos disponibles por haber instalado el lenguaje en la computadora.

Y dentro de la biblioteca estándar tenemos un puñado de funciones tan pero tan cercanas a Python que ni siquiera se necesita importarlas. Se pueden usar por el solo hecho de programar en Python. Por ejemplo, "print()". Son las funciones incorporadas.

Por el momento veremos unas pocas funciones. Una de ellas, ascii(), dará pie para una interesante explicación sobre Unicode y los números hexadecimales.

abs(x)

Devuelve el valor absoluto de x.

abs(8) # 8

abs(-8) # 8


all(x)

x debe ser un iterable. all verificará de una sola vez todos los elementos de x y devolverá True si todos los elementos de x son verdaderos. También devolverá True si x no tiene elementos.

Permite evaluar distintas condiciones.

También permite descubrir si uno o más de una lista de números es 0.

a = [3<4, 8==8, "A"<"B", 1]

print(all(a)) # True

a = [] # Vacío

print(all(a)) # True

a = [3<4, 8==8, "A"<"B", 0] # El 0 se considera Falso

print(all(a)) # False


any(x)

x debe ser un iterable. any verificará de una sola vez todos los elementos de x y devolverá True si al menos un elemento de x es verdadero. Si todos son falsos o x está vacío, devolverá False.

Permite evaluar distintas condiciones.

Un entero distinto a 0 se considera True, el 0 se considera False (también en if, etc.)

a = [3 > 4, 8 != 8, "A" > "B", (2+3-5)] # una expresión que resulte en 0 es False

print(any(a))  # False

a = []  # Vacío

print(any(a))  # False

a = [3 > 4, 8 != 8, "A" > "B", 9]  # Cualquier entero distinto a 0 es True

print(any(a))  # True


ascii(x)

x debe ser un objeto (incluyendo iterables). Devuelve una cadena de caracteres que representa una versión imprimible del objeto.

Por ejemplo en el caso de un objeto vemos que devuelve una cadena con la clase y la dirección de memoria que aloja al objeto:

class Bot: # definimos una clase para el ejemplo

    def switch_on(self):

        print("¡Hola! Soy tu amigo virtual.")

    def switch_off(self):

        print("¡Adios! Nos veremos pronto.")

friend = Bot() # creamos un objeto

print(ascii(friend)) # imprime <__main__.Bot object at 0x000001A06E81CDF0>


Otro ejemplo (con interables) donde vemos que ascii() reemplaza caracteres que no son ASCII estándar (es decir, tienen un código ASCII por encima de 127 o directamente son Unicode) por caracteres escapados:

a = [1, 2, "3", "moño", "¿qué?", "🎨", "ئ"]

x = ascii(a)

print(a) # [1, 2, '3', 'moño', '¿qué?', '🎨', 'ئ']

print(x) # [1, 2, '3', 'mo\xf1o', '\xbfqu\xe9?', '\U0001f3a8', '\u0626']


Qué es el escapado hecho por ascii()

Esto lo investigué por mí mismo, ya que era algo que me generaba dudas y no aclararlo era lo mismo que quedarse con cualquier definición sacada de Internet. Es una información que sirve para muchas cosas, tiene que ver con Unicode y cómo se representa numéricamente.

La función ascii() "filtra" o reemplaza cualquier carácter que exceda al viejísimo pero infalible ASCII estándar (128 caracteres), incluyendo A-Z, a-z, 0-9, y unos cuantos símbolos, pero que no incluye acentos, eñe, cedilla, apertura de exclamación e interrogación, diéresis, y menos aún símbolos matemáticos o chinos. Y menos que menos, emojis.

En el ejemplo de arriba vemos que la "ñ" de "moño", al exceder el carácter ASCII 127, se reemplazó con: \xf1

Esto es el número hexadecimal "f1". La "ñ" tiene el código Unicode 241, que en hexadecimal es f1.

Del mismo modo, el signo apertura de interrogación ("¿") que tampoco pertenece al ASCII estándar, se representa con: \xbf.

Esto representa al símbolo "¿". bf en decimal es 191. Es el código Unicode 191.

Más adelante en el ejemplo hay ¡un emoji! La función ascii() lo expresa como \U0001f3a8. Esto es "\U" seguido de un número hexadecimal de 4 bytes (cada 2 dígitos en haxadecimal es un byte, y aquí tenemos 8).

Notemos que para caracteres cuyo código se puede expresar con un byte, como la "ñ", el prefijo es "\x", mientras que si el código es de 4 bytes el prefijo es "\U".

Finalmente, para ver todos los casos (o eso creo) agregué un carácter del alfabeto árabe cuyo código es de 2 bytes y se expresa con el número hexadecimal 0626. El prefijo es "\u" (u minúscula).

De hecho el tema Unicode es amplio.

Tenemos UTF-8, UTF-16 y UTF-32. Eso son los bits que ocupa cada carácter en cada sistema. Podríamos pensar con lógica que 8 bits alcanzan para representar caracteres de 1 byte, 16 bits para caracteres de 2 bytes y 32 bits para caracteres de 4 bytes, pero es más complejo que eso.

En realidad UTF-8 puede representar caracteres de 4 bytes. Esto evita desperdiciar 4 bytes en caracteres que sólo necesitan 1, como sucede al usar UTF-32. Pero usando mecanismos que -espero- pueda explicar en otra oportunidad.


bin(x)

x debe ser un número entero. Flotantes darán un error.

Devuelve una cadena que representa a x convertido a binario. La cadena siempre comienza con el prefijo "0b".

print(bin(78)) # 0b1001110

print(bin(1400)) # 0b10101111000

Si no se desea el prefijo "0b" puede usarse format() con el código de formato "b", ya que "b" tiene el mismo efecto que bin().

print(format(78,"b")) # 1001110

print(format(1400,"b")) # 10101111000


bool(x)

x puede ser cualquier expresión u objeto, y bool() la convertirá a True o False. El criterio exacto es el procedimiento de prueba de veracidad que puede consultarse en la documentación de Python siguiendo el enlace.

Un objeto vacío (cadena, tupla, matriz, diccionario) se considera False. Una cadena conteniendo un espacio no se considera vacía, da True.

Un número se considera False si es 0, en otro caso resulta en True

Normalmente la instrucción if no necesita usar bool(), lo hace implícitamente. En cambio, si deseamos que el True o False deducido de una expresión x quede en una variable, se usa bool()

j = 0
if j: # no se ejecuta, asume False

j = "XYZ"
if j: # se ejecuta, asume True

j = {}
if j: # no se ejecuta, asume False

j = -1
v = bool(j) # almacena True


chr(x)

Devuelve el carácter correspondiente al código Unicode x.

Esto guarda cierta relación con la función ascii() que veíamos antes. Los valores admitidos para x están entre 0 y 1.114.111 (0x10FFFF en hexadecimal).

print(chr(65)) # A

print(chr(615)) # ɧ

print(chr(128013)) # 🐍 ¡una serpiente!


divmod(x, y)

Devuelve una tupla conteniendo el resultado y el resto de dividir x por y.

En el ejemplo de abajo, se utiliza divmod() para dividir 7 entre 3. El resultado devuelto se aloja en la tupla a, que se puede consultar como a[0] (el cociente) y a[1] (el resto).

a=divmod(7,3)

print(a[0],a[1]) # 2 1

Con valores enteros los resultados son exactos, mientas que si los valores pasados a divmod() son de punto flotante, el resto de la división quedará como si se le aplicara la función floor() (se redondea hacia el inferior, y esto, en el caso de números negativos, significa que -4.00006 se redondea a -5).


float(x)

Devuelve un valor float a partir de x, que puede ser cualquier valor convertible a número. Esto incluye enteros, cadenas que representen un número (aunque esté en notación científica), valores booleanos (resultan en 1.0 o 0.0) y números en hexadecimal, binario, octal, etc., que Python permite escribir si se les antepone "0x".

También es útil para transformar una entrada por teclado, que viene como cadena (como las obtenidas con input()), en un valor que pueda usarse en cálculos sin generar un error.

print(float(1)) # 1.0
print(float("14")) # 14.0
print(float("5E+4")) # 50000.0
print(float("True")) # 1
print(float(0xFF1A)) # 65306.0


hasattr(objeto, atributo)

objeto es un objeto existente. atributo es una cadena con el nombre de un atributo que se desea comprobar si existe en el objeto.

Es útil al programar con orientación a objetos. Cuando se trabaja sobre un objeto que no se puede precisar con exactitud, puede verificarse si una propiedad o método existe antes de utilizarlos.

# Define la clase Bot
class Bot:
    def switch_on(self): # un método
        print("Hola! Soy tu amigo virtual")
    def switch_off(self): # otro método
        print("Adios! Nos veremos pronto!")

# Crea un objeto llamado "friend"
friend = Bot()

print(hasattr(friend,"switch_off")) # True, el método "switch_off()" existe
print(hasattr(friend,"nick")) # False, no hay método ni propiedad "nick"


No hay comentarios.:

Publicar un comentario