
La sintaxis del lenguaje de programación Python es el conjunto de reglas que define cómo se escribirá e interpretará un programa Python (tanto por el sistema de ejecución como por programadores). Python comparte muchas similitudes con Perl , C y Java . Sin embargo, existen diferencias importantes entre estos lenguajes. Admite múltiples paradigmas de programación , incluyendo la programación estructurada, la programación orientada a objetos y la programación funcional , y cuenta con un sistema de tipos dinámico y gestión automática de memoria .
La sintaxis de Python es simple y consistente, y se rige por el principio de que "debe haber una —y preferiblemente solo una— manera obvia de hacerlo". El lenguaje incorpora tipos de datos y estructuras integrados , mecanismos de control de flujo , funciones de primera clase y módulos para una mejor reutilización y organización del código . Python también utiliza palabras clave en inglés donde otros lenguajes usan signos de puntuación, lo que contribuye a su diseño visual claro y ordenado.
El lenguaje ofrece un manejo de errores robusto mediante excepciones e incluye un depurador en la biblioteca estándar para una resolución de problemas eficiente. La sintaxis de Python, diseñada para ser legible y fácil de usar, la convierte en una opción popular tanto para principiantes como para profesionales.
Filosofía del diseño
Python fue diseñado para ser un lenguaje altamente legible . [ 1 ] Tiene una disposición visual relativamente despejada y usa palabras clave en inglés con frecuencia donde otros lenguajes usan signos de puntuación . Python busca ser simple y consistente en el diseño de su sintaxis, encapsulado en el mantra "Debe haber una —y preferiblemente solo una— manera obvia de hacerlo" , del Zen de Python . [ 2 ]
Este mantra se opone deliberadamente al mantra de Perl y Ruby : " hay más de una manera de hacerlo ".
Palabras clave
Python 3 tiene 35 palabras clave o palabras reservadas ; no se pueden usar como identificadores . [ 3 ] [ 4 ]
andasassertasync[ nota 1 ]await[ nota 1 ]breakclasscontinuedefdelelifelseexceptFalse[ nota 2 ]finallyforfromglobalifimportinislambdaNonenonlocal[ nota 3 ]notorpassraisereturnTrue[ nota 2 ]trywhilewithyield
Además, Python 3 también tiene 4 palabras clave suaves , incluyendo typeuna añadida en Python 3.12. A diferencia de las palabras clave duras regulares , las palabras clave suaves son palabras reservadas solo en contextos limitados donde interpretarlas como palabras clave tendría sentido sintáctico. Estas palabras pueden usarse como identificadores en otros lugares; en otras palabras, `match` y ` case` son nombres válidos para funciones y variables. [ 6 ] [ 7 ]
_[ nota 4 ]case[ nota 4 ]match[ nota 4 ]type
Anotaciones de funciones
Las anotaciones de funciones (sugerencias de tipo) se definen en PEP 3107. [ 8 ] Permiten adjuntar datos a los argumentos y al valor de retorno de una función. El lenguaje no define el acto de usar anotaciones, sino que se deja a los frameworks de terceros. Por ejemplo, se podría escribir una biblioteca para manejar el tipado estático: [ 8 ]
def haul ( item : Haulable , * vargs : PackAnimal ) -> Distance : # implementación aquíSi bien las anotaciones son opcionales en Python, el resto de este artículo las utilizará para brindar mayor claridad.
Módulos y declaraciones de importación
En Python, el código se organiza en archivos llamados módulos , y los espacios de nombres se definen en cada módulo. Dado que los módulos pueden estar contenidos en paquetes jerárquicos, los espacios de nombres también son jerárquicos. [ 9 ] [ 10 ] En general, cuando se importa un módulo, los nombres definidos en él se definen a través del espacio de nombres de ese módulo, y se accede a ellos desde los módulos que lo llaman utilizando el nombre completo.
# Supongamos que ModuleA define dos funciones: func1() y func2() y una clase: Class1 import ModuleAModuleA.func1 ( ) ModuleA.func2 ( ) a : ModuleA.Class1 = Modulea.Class1 ( )La from ... import ...instrucción se puede utilizar para insertar los nombres relevantes directamente en el espacio de nombres del módulo que realiza la llamada, y se puede acceder a esos nombres desde el módulo que realiza la llamada sin el nombre calificado:
# Supongamos que ModuleA define dos funciones: func1() y func2() y una clase: Class1 from ModuleA import func1func1 () func2 () # esto fallará como nombre indefinido, al igual que el nombre completo ModuleA.func2() a : Class1 = Class1 () # esto fallará como nombre indefinido, al igual que el nombre completo ModuleA.Class1()Dado que esto importa nombres directamente (sin ninguna condición), puede sobrescribir los nombres existentes sin advertencias.
Una forma especial de la instrucción es from ... import *que importa todos los nombres definidos en el paquete nombrado directamente en el espacio de nombres del módulo que realiza la llamada. El uso de esta forma de importación, aunque está soportada por el lenguaje, generalmente se desaconseja ya que contamina el espacio de nombres del módulo que realiza la llamada y hará que los nombres ya definidos se sobrescriban en caso de conflictos de nombres. [ 11 ] Sin embargo, esta página presentará el código como si from typing import *se incluyera la línea " ", para hacer referencia a los tipos de colección.
Aquí se muestran las diferentes declaraciones de importación:
# importa el módulo de análisis de argumentos import argparse # importa la clase Pattern del módulo de expresiones regulares from re import Pattern # importa todos los símbolos dentro del módulo typing from typing import *El uso from importde sentencias en Python puede simplificar los espacios de nombres extensos, como los espacios de nombres anidados.
from selenium.webdriver import Firefox from selenium.webdriver.common.action_chains import ActionChains from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys from selenium.webdriver.remote.webelement import WebElementif __name__ == " __main__ " : driver : Firefox = Firefox ( ) element : WebElement = driver.find_element ( By.ID , " myInputField " ) element.send_keys ( f " Hola Mundo { Keys.ENTER } " ) action : ActionChains = ActionChains ( driver ) action.key_down ( Keys.CONTROL ) .send_keys ( " a " ) . key_up ( Keys.CONTROL ) .perform ( )Python también admite import x as ycomo una forma de proporcionar un alias o nombre alternativo para que lo utilice el módulo que realiza la llamada:
import numpy as np from numpy.typing import NDArray , float32a : NDArray [ float32 ] = np . organizar ( 1000 )Cuando se importa un módulo, el intérprete de Python primero verifica si existe en la sys.modulescaché y lo reutiliza si se importó previamente; de lo contrario, lo carga. Al cargarlo, lo busca en sys.pathy lo compila a bytecode o interpreta su contenido. Se ejecuta todo el código en el ámbito global del módulo. Sin embargo, esto se puede mitigar utilizando una función main explícita, que se comporta de manera similar a un punto de entrada en la mayoría de los lenguajes compilados, utilizando el patrón de punto de entrada que se describe a continuación.
Punto de entrada
Se puede crear un punto de entrada pseudo mediante el siguiente modismo, que se basa en que la variable interna __name__se establezca __main__cuando se ejecuta un programa, pero no cuando se importa como un módulo (en cuyo caso se establece en su lugar al nombre del módulo); existen muchas variantes de esta estructura: [ 12 ] [ 13 ] [ 14 ]
importar sysdef main ( argv : list [ str ]) -> int : argc : int = len ( argv ) # obtener la longitud de argv n : int = int ( argv [ 1 ]) print ( n + 1 ) return 0if __name__ == "__main__" : sys . exit ( main ( sys . argv ))En este estilo, la llamada al punto de entrada especificado maines explícita, y la interacción con el sistema operativo (recepción de argumentos, llamada a la función de salida del sistema) se realiza explícitamente mediante llamadas a la biblioteca, que en última instancia son gestionadas por el entorno de ejecución de Python. Esto contrasta con C, donde estas interacciones se realizan implícitamente por el entorno de ejecución, según una convención.
Sangría
Python utiliza espacios en blanco para delimitar los bloques de control de flujo (siguiendo la regla de fuera de línea ). Python toma prestada esta característica de su predecesor ABC : en lugar de signos de puntuación o palabras clave, utiliza la indentación para indicar la secuencia de un bloque .
En los lenguajes denominados de formato libre —que utilizan la estructura de bloques derivada de ALGOL— los bloques de código se delimitan con llaves ( ) o palabras clave. En la mayoría de las convenciones de codificación para estos lenguajes, los programadores suelen indentar el código dentro de un bloque para diferenciarlo visualmente del código circundante.{ }
Una función recursiva llamada , a la que se le pasa un único parámetro , , y si el parámetro es 0 llamará a una función diferente llamada y de lo contrario llamará , pasando , y también se llamará a sí misma recursivamente, pasando como parámetro, podría implementarse de esta manera en Python:fooxbarbazxx-1
def foo ( x : int ) -> None : if x == 0 : bar () else : baz ( x ) foo ( x - 1 )y podría escribirse así en C :
void foo ( int x ) { if ( x == 0 ) { bar (); } else { baz ( x ); foo ( x - 1 ); } }Un código con sangría incorrecta podría ser malinterpretado por un lector humano de manera diferente a como lo interpretaría un compilador o intérprete. Por ejemplo, si la llamada a la función foo(x - 1)en la última línea del ejemplo anterior tuviera una sangría errónea fuera del bloque / if:else
def foo ( x : int ) -> None : if x == 0 : bar () else : baz ( x ) foo ( x - 1 )Esto provocaría que la última línea siempre se ejecutara, incluso cuando xes 0, lo que resultaría en una recursión infinita .
Aunque tanto los espacios como las tabulaciones se aceptan como formas de indentación y se puede usar cualquier múltiplo de espacios, se recomiendan los espacios [ 15 ] y cuatro espacios (como en los ejemplos anteriores) son, con mucho, los más utilizados. [ 16 ] [ 17 ] No se permite mezclar espacios y tabulaciones en líneas consecutivas a partir de Python 3 [ 18 ] porque puede crear errores difíciles de ver, ya que muchos editores de texto no distinguen visualmente los espacios y las tabulaciones.
Estructuras de datos
Dado que Python es un lenguaje de tipado dinámico , los valores de Python, no las variables, contienen información de tipo . Todas las variables en Python contienen referencias a objetos , y estas referencias se pasan a las funciones. Algunas personas (incluido el propio creador de Python, Guido van Rossum ) han denominado a este esquema de paso de parámetros "llamada por referencia de objeto". Una referencia de objeto es un nombre, y la referencia pasada es un "alias", es decir, una copia de la referencia al mismo objeto, al igual que en C/ C++ . El valor del objeto puede modificarse en la función llamada con el "alias", por ejemplo:
my_list : lista [ str ] = [ "a" , "b" , "c" ] def my_func ( l : lista [ str ]) -> None : l . append ( "x" ) print ( l )print ( my_func ( my_list )) # imprime ['a', 'b', 'c', 'x'] print ( my_list ) # imprime ['a', 'b', 'c', 'x']La función my_funccambia el valor de my_listcon el argumento formal l, que es un alias de my_list. Sin embargo, cualquier intento de operar (asignar una nueva referencia de objeto a) sobre el alias en sí no tendrá ningún efecto sobre el objeto original.
mi_lista : lista [ str ] = [ "a" , "b" , "c" ]def my_func ( l : list [ str ]) -> None : # l.append("x") l = l + [ "x" ] # una nueva lista creada y asignada a l significa que l ya no es un alias de my_list print ( l )print ( my_func ( my_list )) # imprime ['a', 'b', 'c', 'x'] print ( my_list ) # imprime ['a', 'b', 'c']En Python, los nombres accesibles que no son locales ni globales declarados son todos alias.
Entre los lenguajes de tipado dinámico, Python cuenta con una comprobación de tipos moderada. La conversión implícita está definida para los tipos numéricos (así como para los booleanos ), por lo que se puede multiplicar válidamente un número complejo por un entero (por ejemplo) sin necesidad de una conversión explícita . Sin embargo, no existe una conversión implícita entre, por ejemplo, números y cadenas ; una cadena es un argumento inválido para una función matemática que espera un número.
Tipos base
Python cuenta con una amplia gama de tipos de datos básicos. Además de la aritmética convencional de enteros y de punto flotante , admite de forma transparente aritmética de precisión arbitraria , números complejos y números decimales .
Python admite una amplia variedad de operaciones con cadenas de caracteres. En Python, las cadenas son inmutables , lo que significa que las operaciones con cadenas, como la sustitución de caracteres , devuelven una nueva cadena; en otros lenguajes de programación, la cadena podría modificarse directamente . En ocasiones, por motivos de rendimiento, se recomienda utilizar técnicas especiales en programas que modifican cadenas de forma intensiva, como unir matrices de caracteres en cadenas solo cuando sea necesario.
Tipos de colección
Uno de los aspectos más útiles de Python es el concepto de tipos de colección (o contenedor ). En general, una colección es un objeto que contiene otros objetos de forma que se puedan referenciar o indexar fácilmente . Las colecciones se presentan en dos formas básicas: secuencias y asignaciones .
Los tipos secuenciales ordenados son listas ( matrices dinámicas ), tuplas y cadenas. Todas las secuencias se indexan posicionalmente ( de 0 a longitud - 1 ) y todas, excepto las cadenas, pueden contener cualquier tipo de objeto, incluyendo varios tipos en la misma secuencia. Tanto las cadenas como las tuplas son inmutables, lo que las convierte en candidatas perfectas para claves de diccionario (véase más abajo). Las listas, por otro lado, son mutables; los elementos se pueden insertar, eliminar, modificar, añadir o reordenar directamente .
Por otro lado, las asignaciones son tipos (a menudo no ordenados) implementados en forma de diccionarios que "mapean" un conjunto de claves inmutables a elementos correspondientes (de forma similar a una función matemática). Por ejemplo, se podría definir un diccionario donde una cadena "toast"se mapee a un entero 42o viceversa. Las claves de un diccionario deben ser de un tipo inmutable de Python, como un entero o una cadena, ya que se implementan mediante una función hash . Esto permite tiempos de búsqueda mucho más rápidos, pero requiere que las claves permanezcan inalteradas.
Los diccionarios son fundamentales para el funcionamiento interno de Python, ya que constituyen la base de todos los objetos y clases: las correspondencias entre los nombres de las variables (cadenas de texto) y los valores a los que hacen referencia se almacenan como diccionarios (véase Sistema de objetos ). Dado que estos diccionarios son directamente accesibles (a través de un __dict__atributo del objeto), la metaprogramación resulta un proceso sencillo y natural en Python.
Un tipo de colección de conjuntos es una colección no indexada y desordenada que no contiene duplicados e implementa operaciones de teoría de conjuntos como unión , intersección , diferencia , diferencia simétrica y prueba de subconjuntos . Hay dos tipos de conjuntos: sety frozenset, la única diferencia es que setes mutable y frozensetes inmutable. Los elementos de un conjunto deben ser hasheables. Por lo tanto, por ejemplo, un frozensetpuede ser un elemento de un regular setmientras que lo contrario no es cierto.
Python también proporciona amplias capacidades para la manipulación de colecciones, como la comprobación de contención integrada y un protocolo de iteración genérico.
Sistema de objetos
En Python, todo es un objeto , incluso las clases . Las clases, como objetos, tienen una clase, que se conoce como su metaclase . Python también admite herencia múltiple y mixins .
El lenguaje admite una introspección exhaustiva de tipos y clases. Los tipos se pueden leer y comparar: los tipos son instancias del objeto type. Los atributos de un objeto se pueden extraer como un diccionario.
En Python, los operadores se pueden sobrecargar definiendo funciones miembro especiales; por ejemplo, definir un método con un nombre específico __add__en una clase permite utilizar el +operador en objetos de esa clase.
Literales
Instrumentos de cuerda
Python tiene varios tipos de literales de cadena .
literales de cadena normales
Se pueden usar comillas simples o dobles para entrecomillar cadenas. A diferencia de los lenguajes de shell de Unix, Perl o lenguajes influenciados por Perl como Ruby o Groovy , las comillas simples y dobles funcionan de forma idéntica, es decir, no hay interpolación de cadenas de expresiones $foo . Sin embargo, la interpolación se puede realizar de varias maneras: con "f-strings" (desde Python 3.6 [ 19 ] ), usando el formatmétodo o el antiguo operador de formato de cadena % .
Por ejemplo, todas estas instrucciones de Python:
imprimir ( f "Acabo de imprimir { num } páginas en la impresora { printer } " )print ( "Acabo de imprimir {} páginas en la impresora {} " . format ( num , printer )) print ( "Acabo de imprimir {0} páginas en la impresora {1} " . format ( num , printer )) print ( "Acabo de imprimir {a} páginas en la impresora {b} " . format ( a = num , b = printer ))print ( "Acabo de imprimir %s páginas en la impresora %s " % ( num , printer )) print ( "Acabo de imprimir %(a)s páginas en la impresora %(b)s " % { "a" : num , "b" : printer })son equivalentes a la instrucción Perl:
Imprimir "Acabo de imprimir $num páginas en la impresora $printer\n"Construyen una cadena usando las variables numy printer.
Literales de cadena de varias líneas
También existen cadenas de varias líneas, que comienzan y terminan con una serie de tres comillas simples o dobles y funcionan como los documentos aquí en Perl y Ruby .
Un ejemplo sencillo con interpolación variable (utilizando el formatmétodo) es:
imprimir ( '''Estimado {destinatario} ,Deseo que te vayas de Sunnydale y no regreses jamás.No es exactamente amor, {sender} ''' .format ( sender = "Buffy la cazavampiros" , recipient = "Spike" ))cuerdas crudas
Finalmente, todos los tipos de cadena mencionados anteriormente vienen en variedades " raw " (indicadas colocando una r literal antes de la comilla de apertura), que no realizan interpolación de barra invertida y por lo tanto son muy útiles para expresiones regulares ; compárese con "@-quoting" en C# . Las cadenas raw se incluyeron originalmente específicamente para expresiones regulares. Debido a limitaciones del tokenizador , las cadenas raw pueden no tener una barra invertida final . [ 20 ] Crear una cadena raw que contenga una ruta de Windows que termine con una barra invertida requiere algún tipo de solución alternativa (comúnmente, usar barras inclinadas hacia adelante en lugar de barras invertidas, ya que Windows acepta ambas).
Algunos ejemplos son:
# Una ruta de Windows, incluso las cadenas sin formato no pueden terminar en una barra invertida win_path : str = r "C:\Foo\Bar\Baz \"# Error: # Archivo "<stdin>", línea 1 # win_path: str = r"C:\Foo\Bar\Baz\" # ^ # SyntaxError: Fin de línea al escanear una cadena literaldos_path : str = r "C:\Foo\Bar\Baz\ " # evita el error agregando print ( dos_path.rstrip ()) # y eliminando el espacio final # prints('C:\\Foo\\Bar\\Baz \\ ' )quoted_dos_path : str = r '" {} "' . format ( dos_path ) print ( quoted_dos_path ) # imprime '"C:\\Foo\\Bar\\Baz\\ "'# Una expresión regular que coincide con una cadena entre comillas con posible comillas invertidas print ( re . match ( r '"(([^" \\ ]| \\ .)*)"' , quoted_dos_path ) . group ( 1 ) . rstrip ()) # imprime 'C:\\Foo\\Bar\\Baz\\'código : str = 'foo(2, bar)' # Invierte los argumentos en una llamada a función de dos argumentos print(re.sub ( r ' \ ( ( [ ^,]*?),([^,]*?)\)' , r '(\2, \1)' , código )) # imprime 'foo(2, bar)' # Tenga en cuenta que esto no funcionará si alguno de los argumentos tiene paréntesis o comas.Concatenación de literales de cadena adyacentes
Se permiten literales de cadena que aparecen de forma contigua y solo están separados por espacios en blanco (incluidas las nuevas líneas mediante barras invertidas), y se agregan en una única cadena más larga. [ 21 ] Por lo tanto
título : str = "Una buena acción: " \ 'Historia natural del destornillador y el tornillo'es equivalente a
Título : str = "Una buena acción: una historia natural del destornillador y el tornillo"Unicode
Desde Python 3.0, el conjunto de caracteres predeterminado es UTF-8 tanto para el código fuente como para el intérprete. En UTF-8, las cadenas Unicode se manejan como cadenas de bytes tradicionales. Este ejemplo funcionará:
s : str = "Γειά" # Hola en griego print ( s )Números
Los literales numéricos en Python son del tipo normal, por ejemplo 0, , -1, 3.4, 3.5e-8.
Python admite enteros de longitud arbitraria y aumenta automáticamente su tamaño de almacenamiento según sea necesario. Antes de Python 3, existían dos tipos de números enteros: los enteros tradicionales de tamaño fijo y los enteros "largos" de tamaño arbitrario. La conversión a enteros "largos" se realizaba automáticamente cuando se requería, por lo que el programador generalmente no tenía que conocer los dos tipos de enteros. En las versiones más recientes del lenguaje, esta distinción ha desaparecido por completo y todos los enteros se comportan como enteros de longitud arbitraria.
Python admite números de punto flotante normales , que se crean cuando se usa un punto en un literal (por ejemplo, 1.1), cuando se usan un entero y un número de punto flotante en una expresión, o como resultado de algunas operaciones matemáticas ("división verdadera" a través del /operador, o exponenciación con un exponente negativo).
Python también admite números complejos de forma nativa. La parte imaginaria de un número complejo se indica con el sufijo Jo , por ejemplo .j3 + 4j
Listas, tuplas, conjuntos, diccionarios
Python cuenta con soporte sintáctico para la creación de tipos de contenedores.
Las listas (clase list) son secuencias mutables de elementos de tipos arbitrarios y se pueden crear con la sintaxis especial
mi_lista : lista [ int | str ] = [ 1 , 2 , 3 , "un perro" ]o utilizando la creación normal de objetos
mi_segunda_lista : lista [ int ] = [ ] mi_segunda_lista.append ( 4 ) mi_segunda_lista.append ( 5 )Las tuplas (clase tuple) son secuencias inmutables de elementos de tipos arbitrarios. También existe una sintaxis especial para crear tuplas.
my_tuple : tuple [ int | str ] = 1 , 2 , 3 , "four" my_tuple : tuple [ int | str ] = ( 1 , 2 , 3 , "four" )Aunque las tuplas se crean separando los elementos con comas, toda la estructura suele ir entre paréntesis para facilitar la lectura. Una tupla vacía se denota con (), mientras que una tupla con un solo valor se puede crear con (1,).
Los conjuntos (clase set) son contenedores mutables de elementos hashables [ 22 ] de tipos arbitrarios, sin duplicados. Los elementos no están ordenados, pero los conjuntos admiten la iteración sobre ellos. La sintaxis para la creación de conjuntos utiliza llaves.
mi_conjunto : conjunto [ Cualquiera ] = { 0 , (), Falso }Los conjuntos de Python son muy similares a los conjuntos matemáticos y admiten operaciones como la intersección y la unión de conjuntos . Python también cuenta con una frozensetclase para conjuntos inmutables; consulte los tipos de colecciones .
Los diccionarios (clase dict) son mapeos mutables que vinculan claves y valores correspondientes. Python tiene una sintaxis especial para crear diccionarios ( {key: value}).
mi_diccionario : dict [ Any , Any ] = { "clave 1" : "valor 1" , 2 : 3 , 4 : []}La sintaxis del diccionario es similar a la sintaxis del conjunto; la diferencia radica en la presencia de dos puntos. El literal vacío {}da como resultado un diccionario vacío en lugar de un conjunto vacío , que se crea utilizando el constructor no literal: set().
Operadores
Aritmética
Python incluye los operadores +, -, *, /("división verdadera"), //( división entera% ), ( módulo ) y **( exponenciación ), con su precedencia matemática habitual .
En Python 3, x / yrealiza una "división verdadera", lo que significa que siempre devuelve un número flotante, incluso si tanto xcomo yson enteros que se dividen exactamente.
imprimir ( 4 / 2 ) # imprime 2.0y //realiza una división entera o una división entera , devolviendo la parte entera del cociente como un número entero.
En Python 2 (y en la mayoría de los demás lenguajes de programación), a menos que se solicitara explícitamente, x / yse realizaba la división entera, devolviendo un número decimal solo si alguno de los datos de entrada era decimal. Sin embargo, debido a que Python es un lenguaje de tipado dinámico, no siempre era posible determinar qué operación se estaba realizando, lo que a menudo generaba errores sutiles. Esto motivó la introducción del //operador y el cambio en la semántica del /operador en Python 3.
Operadores de comparación
Los operadores de comparación, es decir ==, !=, , <, >, <=, >=, is, is not, iny not in[ 23 ] se utilizan en todo tipo de valores. Se pueden comparar números, cadenas, secuencias y asignaciones. En Python 3, los tipos dispares (como a stry an int) no tienen un orden relativo consistente, y los intentos de comparar estos tipos generan una TypeErrorexcepción. Si bien era posible comparar tipos dispares en Python 2 (por ejemplo, si una cadena era mayor o menor que un entero), el orden no estaba definido; esto se consideró una peculiaridad de diseño histórica y finalmente se eliminó en Python 3.
Las expresiones de comparación encadenadas, como esta, a < b < ctienen aproximadamente el mismo significado que en matemáticas, en lugar del significado inusual que se encuentra en C y lenguajes similares. Los términos se evalúan y comparan en orden. La operación tiene semántica de cortocircuito , lo que significa que se garantiza que la evaluación se detendrá tan pronto como se obtenga un veredicto claro: si a < bes falso, cnunca se evalúa, ya que la expresión ya no puede ser verdadera.
Para expresiones sin efectos secundarios, a < b < ces equivalente a a < b and b < c. Sin embargo, existe una diferencia sustancial cuando las expresiones tienen efectos secundarios. a < f(x) < bse evaluará f(x)exactamente una vez, mientras que a < f(x) and f(x) < bse evaluará dos veces si el valor de aes menor que f(x)y una vez en caso contrario.
Operadores lógicos
En todas las versiones de Python, los operadores booleanos tratan los valores cero o vacíos, como "", 0, None, 0.0, [], y {}, como falsos, mientras que en general tratan los valores no vacíos y distintos de cero como verdaderos. Los valores booleanos Truey Falsese agregaron al lenguaje en Python 2.2.1 como constantes (subclases de 1y 0) y se convirtieron en palabras clave completas en Python 3. Los operadores de comparación binaria, como ==y , >devuelven Trueo False.
Los operadores booleanos andy orutilizan una evaluación mínima . Por ejemplo, nunca generará una excepción de división por cero. Estos operadores devuelven el valor del último operando evaluado, en lugar de o . Por lo tanto, la expresión se evalúa como , y se evalúa como .y == 0 or x/y > 100TrueFalse(4 and 5)5(4 or 5)4
operadores bit a bit
Python puede realizar operaciones bit a bit en enteros o números binarios escritos con el 0bprefijo. Utiliza x << ypara desplazar xa la izquierda yposiciones, añadiendo ceros a la derecha. x >> yhace lo mismo pero desplaza xa la derecha, añadiendo copias del bit más a la izquierda. El operador x & yrealiza un AND bit a bit, x | yrealiza un OR bit a bit, ~ xdevuelve el complemento bit a bit/NOT de x, y x ^ yrealiza un XOR bit a bit, contrariamente al ^uso habitual del símbolo como operador de exponenciación. [ 24 ] [ 25 ]
Programación funcional
Una de las ventajas de Python es la disponibilidad de un estilo de programación funcional , lo que hace que trabajar con listas y otras colecciones sea mucho más sencillo.
Comprensión
Una de estas construcciones es la comprensión de listas , que se puede expresar con el siguiente formato:
l : lista [ Cualquier ] = [ expresión_de_mapeo para elemento en lista_de_origen si expresión_de_filtro ]Utilizando la comprensión de listas para calcular las primeras cinco potencias de dos:
potencias_de_dos : lista [ int ] = [ 2 ** n para n en rango ( 1 , 6 )]El algoritmo Quicksort se puede expresar de forma elegante (aunque ineficiente) utilizando comprensiones de listas:
T : TypeVar = TypeVar ( "T" )def qsort ( l : lista [ T ]) -> lista [ T ]: if l == []: return [] pivot : T = l [ 0 ] return ( qsort ([ x for x in l [ 1 :] if x < pivot ]) + [ pivot ] + qsort ([ x for x in l [ 1 :] if x >= pivot ]))Python 2.7+ [ 26 ] también admite comprensiones de conjuntos [ 27 ] y comprensiones de diccionarios. [ 28 ]
Funciones de primera clase
En Python, las funciones son objetos de primera clase que se pueden crear y pasar dinámicamente.
El soporte limitado de Python para funciones anónimas es la lambdaconstrucción. Un ejemplo es la función anónima que eleva al cuadrado su entrada, llamada con el argumento 5:
f : Llamable [[ int ], int ] = lambda x : x ** 2 f ( 5 )Las expresiones lambda se limitan a contener una expresión en lugar de sentencias , aunque el flujo de control aún puede implementarse de forma menos elegante dentro de lambda mediante el uso de cortocircuito, [ 29 ] y de forma más idiomática con expresiones condicionales. [ 30 ]
Cierres
Python admite cierres léxicos desde la versión 2.2. Aquí hay un ejemplo de función que devuelve una función que aproxima la derivada de la función dada:
def derivada ( f : Llamable [[ float ], float ], dx : float ): """Devuelve una función que aproxima la derivada de f usando un intervalo de dx, que debe ser suficientemente pequeño. """ def función ( x : float ) -> float : return ( f ( x + dx ) - f ( x )) / dx return funciónSin embargo, la sintaxis de Python a veces lleva a los programadores de otros lenguajes a pensar que no admite cierres. El ámbito de las variables en Python se determina implícitamente por el ámbito en el que se asigna un valor a la variable, a menos que el ámbito se declare explícitamente con globalo nonlocal. [ 31 ]
Tenga en cuenta que la vinculación de un nombre a un valor dentro del cierre no es mutable desde dentro de la función. Dado:
def foo ( a : int , b : int ) -> None : print ( f "a: { a } " ) print ( f "b: { b } " ) def bar ( c : int ) -> None : b = c print ( f "b*: { b } " ) bar ( a ) print ( f "b: { b } " )print ( foo ( 1 , 2 )) # imprime: # a: 1 # b: 2 # b*: 1 # b: 2y puedes ver que b, como se ve desde el ámbito del cierre, conserva el valor que tenía; el enlace cambiado de bdentro de la función interna no se propagó. La forma de evitar esto es usar una nonlocal binstrucción en bar. En Python 2 (que carece de nonlocal), la solución habitual es usar un valor mutable y cambiar ese valor, no el enlace. Por ejemplo, una lista con un elemento.
Generadores
Introducidos en Python 2.2 como una característica opcional y finalizados en la versión 2.3, los generadores son el mecanismo de Python para la evaluación perezosa de una función que, de otro modo, devolvería una lista demasiado voluminosa o computacionalmente intensiva.
Este es un ejemplo para generar números primos de forma perezosa:
importar itertoolsdef generate_primes ( stop_at : Optional [ int ] = None ) -> Iterator [ int ]: primes : list [ int ] = [] for n in itertools . count ( start = 2 ): if stop_at is not None and n > stop_at : return # genera la excepción StopIteration composite : bool = False for p in primes : if not n % p : composite = True break elif p ** 2 > n : break if not composite : primes . append ( n ) yield nAl llamar a esta función, el valor devuelto se puede recorrer de forma similar a como se recorre una lista:
for i in generate_primes ( 100 ): # iterar sobre los números primos entre 0 y 100 print ( i )for i in generate_primes (): # iterar sobre TODOS los números primos indefinidamente print ( i )La definición de un generador es idéntica a la de una función, salvo que yieldse utiliza la palabra clave en lugar de return. Sin embargo, un generador es un objeto con estado persistente, que puede entrar y salir repetidamente del mismo ámbito. Por lo tanto, se puede usar una llamada a un generador en lugar de una lista u otra estructura cuyos elementos se iterarán. Siempre que el forbucle del ejemplo requiera el siguiente elemento, se llama al generador, que lo devuelve.
Los generadores no tienen por qué ser infinitos, como en el ejemplo de los números primos. Cuando un generador finaliza, se produce una excepción interna que indica a cualquier contexto que lo llame que ya no hay valores disponibles. forEn consecuencia, el bucle u otra iteración finalizará.
Expresiones generadoras
Introducidas en Python 2.4, las expresiones generadoras son el equivalente de evaluación perezosa de las comprensiones de listas. Usando el generador de números primos proporcionado en la sección anterior, podríamos definir una colección perezosa, pero no del todo infinita.
importar itertoolsprimes_under_million : Iterador [ int ] = ( i para i en generate_primes ( ) si i < 1000000 ) two_thousandth_prime : Iterador [ int ] = itertools.islice ( primes_under_million , 1999 , 2000 ) .next ( )La mayor parte de la memoria y el tiempo necesarios para generar tantos números primos no se utilizarán hasta que se acceda al elemento necesario. Desafortunadamente, no se puede realizar una indexación y segmentación sencillas de los generadores, sino que hay que usar el módulo itertools o crear bucles personalizados. En cambio, una comprensión de lista es funcionalmente equivalente, pero consume muchos recursos al realizar todo el trabajo.
primes_under_million : lista [ int ] = [ i para i en generate_primes ( 2000000 ) si i < 1000000 ] two_thousandth_prime : int = primes_under_million [ 1999 ]La comprensión de listas crea inmediatamente una lista grande (con 78498 elementos en el ejemplo, pero que temporalmente crea una lista de números primos menores de dos millones), incluso si la mayoría de los elementos nunca se utilizan. La comprensión de generadores es más parsimoniosa.
Comprensión de diccionarios y conjuntos
Si bien las listas y los generadores tenían comprensiones/expresiones, en las versiones de Python anteriores a la 2.7, los otros tipos de colecciones integradas de Python (diccionarios y conjuntos) tenían que ser modificados mediante el uso de listas o generadores:
cuadrados = dict (( n , n * n ) for n in range ( 5 )) # en Python 3.5 y posteriores el tipo de cuadrados es dict[int, int] print ( cuadrados ) # imprime {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}Python 2.7 y 3.0 unificaron todos los tipos de colecciones al introducir comprensiones de diccionarios y conjuntos, similares a las comprensiones de listas:
print ([ n * n for n in range ( 5 )]) # comprensión de lista regular # imprime [0, 1, 4, 9, 16] print ({ n * n for n in range ( 5 )}) # comprensión de conjunto # imprime {0, 1, 4, 9, 16} print ({ n : n * n for n in range ( 5 )}) # comprensión de diccionario # imprime {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}objetos
Python admite la mayoría de las técnicas de programación orientada a objetos (POO). Permite el polimorfismo , no solo dentro de una jerarquía de clases , sino también mediante el tipado dinámico (duck typing ). Cualquier objeto puede usarse para cualquier tipo, y funcionará siempre que tenga los métodos y atributos adecuados. En Python, todo es un objeto, incluyendo clases, funciones, números y módulos. Python también admite metaclases , una herramienta avanzada para mejorar la funcionalidad de las clases. Naturalmente, admite la herencia , incluyendo la herencia múltiple . Python tiene un soporte muy limitado para variables privadas mediante la modificación de nombres (name mangling) , que rara vez se usa en la práctica, ya que algunos consideran que ocultar información no es propio de Python , pues sugiere que la clase en cuestión contiene detalles internos poco estéticos o mal planificados. El lema "somos todos usuarios responsables aquí" se usa para describir esta actitud. [ 32 ]
Al igual que ocurre con los módulos, las clases en Python no establecen una barrera absoluta entre la definición y el usuario, sino que confían en la cortesía del usuario para no "interferir en la definición".
— 9. Clases , El tutorial de Python 2.6 (2013)
En Python no se imponen doctrinas de la programación orientada a objetos (POO), como el uso de métodos de acceso para leer miembros de datos. Así como Python ofrece construcciones de programación funcional pero no exige transparencia referencial , ofrece un sistema de objetos pero no exige un comportamiento orientado a objetos . Además, siempre es posible redefinir la clase usando propiedades (ver Propiedades ) de modo que cuando se establece o recupera una variable determinada en el código que la llama, en realidad se invoca una llamada a función, lo que spam.eggs = toastpodría invocar realmente spam.set_eggs(toast). Esto anula la ventaja práctica de las funciones de acceso y sigue siendo POO porque la propiedad eggsse convierte en una parte legítima de la interfaz del objeto: no tiene por qué reflejar un detalle de implementación.
En la versión 2.2 de Python, se introdujeron las clases de "nuevo estilo". Con estas clases, los objetos y los tipos se unificaron, permitiendo la herencia de tipos. Incluso se pueden definir tipos completamente nuevos, con un comportamiento personalizado para los operadores infijos. Esto posibilita realizar numerosas modificaciones sintácticas radicales en Python. En la versión 2.3, también se adoptó un nuevo orden de resolución de métodos para la herencia múltiple. Asimismo, es posible ejecutar código personalizado al acceder o modificar atributos, aunque los detalles de estas técnicas han evolucionado entre las distintas versiones de Python.
Con declaración
La withinstrucción gestiona los recursos y permite a los usuarios trabajar con el protocolo Context Manager. [ 33 ]__enter__() Se llama a una función ( ) al entrar en el ámbito y a otra ( __exit__()) al salir. Esto evita olvidar liberar el recurso y también gestiona situaciones más complejas, como liberar el recurso cuando se produce una excepción mientras está en uso. Los Context Managers se utilizan a menudo con archivos, conexiones a bases de datos, casos de prueba, etc.
Propiedades
Las propiedades permiten invocar métodos definidos específicamente en una instancia de objeto utilizando la misma sintaxis que se usa para acceder a los atributos. Un ejemplo de una clase que define algunas propiedades es:
clase MyClass : def __init __ ( self ) - > None : self._a : int = 0@property def a ( self ) -> int : return self . _a@a . setter # hace que la propiedad sea modificable def a ( self , value : int ) -> None : self . _a = valueDescriptores
Una clase que define uno o más de los tres métodos especiales __get__(self, instance, owner), __set__(self, instance, value), __delete__(self, instance)puede usarse como descriptor. Crear una instancia de un descriptor como miembro de una segunda clase hace que la instancia sea una propiedad de la segunda clase. [ 34 ]
Métodos de clase y estáticos
Python permite la creación de métodos de clase y métodos estáticos mediante el uso de los decoradores `@classmethod class` y `static`. El primer argumento de un método de clase es el objeto de la clase en lugar de la autorreferencia a la instancia. Un método estático no tiene un primer argumento especial. Ni la instancia ni el objeto de la clase se pasan a un método estático.@staticmethod
Excepciones
Python admite (y utiliza ampliamente) el manejo de excepciones como un medio para comprobar si hay errores u otros eventos "excepcionales" en un programa.
El estilo de programación en Python exige el uso de excepciones siempre que pueda surgir un error. En lugar de comprobar si se puede acceder a un archivo o recurso antes de usarlo, en Python es habitual intentar usarlo directamente y capturar la excepción si se rechaza el acceso.
Las excepciones también pueden utilizarse como un medio más general de transferencia de control no local, incluso cuando no se trata de un error. Por ejemplo, el software de listas de correo Mailman , escrito en Python, utiliza excepciones para salir de una lógica de gestión de mensajes muy compleja cuando se ha decidido rechazar un mensaje o retenerlo para su aprobación por parte de un moderador.
Las excepciones se utilizan a menudo como alternativa al ifbloque `-block`, especialmente en situaciones multihilo . Un lema comúnmente invocado es EAFP, o "Es más fácil pedir perdón que permiso" [ 35 ] , que se atribuye a Grace Hopper . [ 36 ] [ 37 ] La alternativa, conocida como LBYL, o "Piensa antes de actuar", comprueba explícitamente las precondiciones. [ 38 ]
En este primer ejemplo de código, siguiendo el enfoque LBYL, se realiza una comprobación explícita del atributo antes del acceso:
if hasattr ( spam , "eggs" ): ham = spam . eggs else : handle_missing_attr ()Esta segunda muestra sigue el paradigma EAFP:
intentar : jamón = spam.huevos excepto AttributeError : handle_missing_attr ( )Estos dos ejemplos de código tienen el mismo efecto, aunque habrá diferencias de rendimiento. Cuando spamtiene el atributo eggs, el ejemplo EAFP se ejecutará más rápido. Cuando spamno tiene el atributo eggs(el caso "excepcional"), el ejemplo EAFP se ejecutará más lento. El perfilador de Python se puede usar en casos específicos para determinar las características de rendimiento. Si los casos excepcionales son raros, entonces la versión EAFP tendrá un rendimiento promedio superior a la alternativa. Además, evita toda la clase de vulnerabilidades de tiempo de verificación a tiempo de uso (TOCTTOU), otras condiciones de carrera , [ 37 ] [ 39 ] y es compatible con el tipado dinámico . Una desventaja de EAFP es que solo se puede usar con sentencias; una excepción no se puede capturar en una expresión generadora, comprensión de lista o función lambda.
Comentarios y cadenas de documentación
Existen dos maneras de anotar código Python. Una consiste en usar comentarios para indicar la función de alguna parte del código. Los comentarios de una sola línea comienzan con el carácter de almohadilla (# #) y continúan hasta el final de la línea. Los comentarios que abarcan más de una línea se logran insertando una cadena de varias líneas (con el carácter de coma """o '''como delimitador en cada extremo) que no se utiliza en asignaciones ni se evalúa de ninguna otra manera, sino que se ubica entre otras instrucciones.
Comentar un fragmento de código:
importar sysdef getline () -> str : return sys . stdin . readline () # Obtiene una línea y la devuelveCómo comentar un fragmento de código con varias líneas:
def getline () -> str : """Esta función obtiene una línea y la devuelve. A modo de ejemplo, esta es una cadena de documentación de varias líneas. Se puede acceder a esta cadena completa como getline.__doc__. """ return sys . stdin . readline ()Las cadenas de documentación ( docstrings ), es decir, las cadenas que se encuentran solas sin asignación como la primera línea indentada dentro de un módulo, clase, método o función, establecen automáticamente su contenido como un atributo llamado __doc__, que está destinado a almacenar una descripción legible para humanos del propósito, comportamiento y uso del objeto. La función integrada helpgenera su salida en función de __doc__los atributos. Dichas cadenas pueden estar delimitadas con "o 'para cadenas de una sola línea, o pueden abarcar varias líneas si están delimitadas con o """, '''que es la notación de Python para especificar cadenas de varias líneas. Sin embargo, la guía de estilo del lenguaje especifica que se prefieren las comillas dobles triples ( """) tanto para cadenas de documentación de una sola línea como para cadenas de varias líneas. [ 40 ]
Cadena de documentación de una sola línea:
def getline () -> str : """Obtiene una línea de stdin y la devuelve.""" return sys . stdin . readline ()Cadena de documentación multilínea:
def getline () -> str : """Obtiene una línea de stdin y la devuelve. """ return sys . stdin . readline ()Las cadenas de documentación pueden ser tan largas como el programador desee y contener saltos de línea . A diferencia de los comentarios, las cadenas de documentación son objetos de Python y forman parte del código interpretado que ejecuta Python. Esto significa que un programa en ejecución puede recuperar sus propias cadenas de documentación y manipular esa información, pero su uso habitual es proporcionar a otros programadores información sobre cómo invocar el objeto documentado en la cadena.
Existen herramientas que permiten extraer las cadenas de documentación del código Python y generar documentación. También se puede acceder a la documentación de las cadenas de documentación desde el intérprete con la help()función, o desde la consola con el comando pydocpydoc .
El módulo estándar doctest utiliza interacciones copiadas de sesiones de shell de Python en cadenas de documentación para crear pruebas, mientras que el módulo docopt las utiliza para definir opciones de línea de comandos.
Decoradores
Un decorador es cualquier objeto invocable de Python que se utiliza para modificar la definición de una función, método o clase. Al decorador se le pasa el objeto original que se está definiendo y devuelve un objeto modificado, que luego se vincula al nombre en la definición. Los decoradores de Python se inspiraron en parte en las anotaciones de Java y tienen una sintaxis similar; la sintaxis del decorador es pura azúcar sintáctica , utilizando @como símbolo. Sin embargo, a diferencia de los atributos generales en la mayoría de los lenguajes de programación, que se utilizan para agregar metadatos ya sea para el compilador o para su lectura en reflexión , los decoradores de Python no se utilizan para adjuntar metadatos, sino como envoltorios ejecutables.
@viking_chorus def menu_item () -> None : print ( "spam" )es equivalente a
def menu_item () -> None : print ( "spam" ) menu_item = viking_chorus ( menu_item )Los decoradores son una forma de metaprogramación ; mejoran la acción de la función o método que decoran. Por ejemplo, en el siguiente ejemplo, viking_choruspodría hacer menu_itemque se ejecute 8 veces (ver boceto de Spam ) por cada vez que se llama:
R : TypeVar = TypeVar ( "R" )def viking_chorus ( myfunc : Callable [ ... , R ]) -> Callable [ ... , None ]: def inner_func ( * args : * tuple [ Any , ... ], ** kwargs : Unpact [ dict [ str , Any ]]) -> None : for i in range ( 8 ): myfunc ( * args , ** kwargs ) return inner_funcLos usos canónicos de los decoradores de funciones son para crear métodos de clase o métodos estáticos , agregar atributos de función, rastrear , establecer precondiciones y postcondiciones , y sincronización , [ 41 ] pero pueden usarse para mucho más, incluyendo la eliminación de recursión de cola , [ 42 ] memorización e incluso mejorar la escritura de otros decoradores. [ 43 ]
Los elementos decorativos se pueden encadenar colocando varios en líneas adyacentes:
@invincible @favourite_colour ( "Azul" ) def black_knight () -> None : passes equivalente a
def black_knight () -> None : pass black_knight = invincible ( favourite_colour ( "Blue" )( black_knight ))o bien, utilizando variables intermedias
def black_knight () -> None : pass blue_decorator = favourite_colour ( "Azul" ) decorated_by_blue = blue_decorator ( black_knight ) black_knight = invincible ( decorated_by_blue )En el ejemplo anterior, la fábricafavourite_colour de decoradores recibe un argumento. Las fábricas de decoradores deben devolver un decorador, que luego se llama con el objeto que se va a decorar como argumento:
def color_favorito ( color : str ) -> Callable [[ Callable [[], R ]], Callable [[], R ]]: def decorador ( func : Callable [[], R ]) -> Callable [[], R ]: def envoltorio () -> R : print ( color ) func () return envoltorio return decoradorEsto decoraría la black_knightfunción de tal manera que el color "Blue"se imprimiría antes de que black_knightse ejecutara. El cierre garantiza que el argumento del color sea accesible para la función contenedora más interna incluso cuando se devuelve y sale del ámbito, lo que permite que los decoradores funcionen.
A pesar de su nombre, los decoradores de Python no son una implementación del patrón decorador . El patrón decorador es un patrón de diseño utilizado en lenguajes de programación orientados a objetos con tipado estático para permitir la adición de funcionalidad a los objetos en tiempo de ejecución; los decoradores de Python añaden funcionalidad a funciones y métodos en el momento de su definición, por lo que constituyen una construcción de nivel superior a las clases del patrón decorador. El patrón decorador en sí es fácilmente implementable en Python, dado que el lenguaje utiliza tipado dinámico (duck type) , por lo que no suele considerarse como tal.
huevos de Pascua
Los usuarios de lenguajes con llaves , como C o Java , a veces esperan o desean que Python siga una convención de delimitación de bloques. La sintaxis de bloques delimitados por llaves se ha solicitado repetidamente, pero los desarrolladores principales la han rechazado sistemáticamente. El intérprete de Python contiene un huevo de Pascua que resume la opinión de sus desarrolladores sobre este tema. El código from __future__ import bracesgenera la excepción SyntaxError: not a chance. El __future__módulo se usa normalmente para proporcionar características de futuras versiones de Python.
Otro mensaje oculto, el Zen de Python (un resumen de la filosofía de diseño de Python ), se muestra al intentar import this.
El mensaje Hello world!se imprime cuando import __hello__se utiliza la instrucción import. En Python 2.7, en lugar de Hello world!eso, imprime Hello world....
La importación del antigravitymódulo abre un navegador web en la tira cómica 353 de xkcd , que muestra un uso ficticio y humorístico de dicho módulo, con el fin de demostrar la facilidad con la que los módulos de Python permiten funcionalidades adicionales. [ 44 ] En Python 3, este módulo también contiene una implementación del algoritmo "geohash", una referencia a la tira cómica 426 de xkcd . [ 45 ]
Notas
Referencias
- ↑ "La legibilidad importa." - PEP 20 - El Zen de Python Archivado el 5 de diciembre de 2014 en Wayback Machine
- ↑ "PEP 20 - El Zen de Python" . Python Software Foundation. 23 de agosto de 2004. Archivado del original el 3 de diciembre de 2008. Consultado el 24 de noviembre de 2008 .
- ↑ "2. Análisis léxico" . Documentación de Python 3. Python Software Foundation . Consultado el 11 de marzo de 2021 .
- ↑ "2. Análisis léxico" . Documentación de Python v2.7.18 . Python Software Foundation . Consultado el 11 de marzo de 2021 .
- ↑ "Nuevas palabras clave" . Documentación de Python v3.5 . Docs.python.org. Archivado del original el 18 de junio de 2016. Consultado el 1 de junio de 2016 .
- ↑ "2. Análisis léxico" . Documentación de Python 3. Python Software Foundation . Consultado el 22 de enero de 2022 .
- ↑ "PEP 622 -- Coincidencia de patrones estructurales" . 23 de junio de 2020. Consultado el 22 de enero de 2022 .
- 1 2 "PEP 3107 -- Anotaciones de funciones" . Archivado del original el 6 de enero de 2015. Recuperado el 15 de agosto de 2014 .
- ↑ "6. Módulos" . El tutorial de Python . Python Software Foundation . Consultado el 25 de octubre de 2010 .
- ↑ "Ámbitos y espacios de nombres de Python" . Docs.python.org . Consultado el 26 de julio de 2011 .
- ↑ https://docs.python.org/3/tutorial/modules.html "En general, la práctica de importar * desde un módulo o paquete no está bien vista"
- ↑ Guido van Rossum (15 de mayo de 2003). "Funciones main() de Python" . Archivado del original el 11 de julio de 2015. Recuperado el 29 de junio de 2015 .comentarios
- ↑ Code Like a Pythonista: Idiomatic Python Archivado el 27/05/2014 en Wayback Machine —sobre scripts de Python utilizados como módulos
- ↑ Ned Batchelder (6 de junio de 2003). "Funciones main() de Python" . Archivado del original el 20 de septiembre de 2015. Consultado el 29 de junio de 2015 .
- ↑ "PEP 8 -- Guía de estilo para código Python" . Python.org . Consultado el 17 de marzo de 2021 .
- ↑ Hoffa, Felipe (26 de julio de 2017). "400.000 repositorios de GitHub, 1.000 millones de archivos, 14 terabytes de código: ¿Espacios o tabulaciones?" . Medium . Consultado el 11 de marzo de 2021 .
- ↑ "Tabulaciones o espacios" . ukupat.github.io . Consultado el 11 de marzo de 2021 .
- ↑ "PEP 8 -- Guía de estilo para código Python" . Python.org . Consultado el 11 de marzo de 2021 .
- ↑ "PEP 498 - Interpolación de cadenas literales" . Novedades de Python 3.6 . 23/12/2016. Archivado del original el 30/03/2017 . Consultado el 29/03/2017 .
- ↑ "2. Análisis léxico" . Documentación de Python v2.7.5 . Docs.python.org. Archivado del original el 23/10/2012 . Consultado el 16/08/2013 .
- ↑ "2. Análisis léxico" . Documentación de Python v2.7.5 . Docs.python.org. Archivado del original el 23/10/2012 . Consultado el 16/08/2013 .
- ↑ Los elementos hasheables suelen ser inmutables, pero no necesariamente por definición. Véase python.org/3/glossary.htm
- ↑ "6. Expresiones — Documentación de Python 3.9.2" . docs.python.org . Consultado el 17 de marzo de 2021 .
- ↑ "Operadores bit a bit - Wiki de Python" . wiki.python.org . Consultado el 2 de diciembre de 2025 .
- ↑ "Operadores bit a bit en Python" . www.w3schools.com . Consultado el 2 de diciembre de 2025 .
- ↑ "Lanzamiento de Python 2.7.0" . Archivado del original el 27 de enero de 2016. Consultado el 19 de enero de 2016 .
- ↑ "5. Estructuras de datos — Documentación de Python 2.7.18" . Archivado del original el 26/01/2016 . Consultado el 19/01/2016 .
- ↑ "5. Estructuras de datos — Documentación de Python 2.7.18" . Archivado del original el 26/01/2016 . Consultado el 19/01/2016 .
- ↑ David Mertz. "Programación funcional en Python" . IBM developerWorks. Archivado del original el 20 de febrero de 2007. Consultado el 27 de agosto de 2007 .
- ↑ "PEP 308 -- Expresiones condicionales" . Archivado del original el 13 de marzo de 2016. Consultado el 14 de abril de 2016 .
- ↑ La
nonlocalpalabra clave fue adoptada por PEP 3104. Archivado el 2 de diciembre de 2014 en Wayback Machine. - ↑ "Guía de estilo de Python" . docs.python-guide.org. Archivado del original el 9 de marzo de 2015. Consultado el 8 de marzo de 2015 .
- ↑ "PEP 343 -- La declaración "con"" . Archivado del original el 14 de diciembre de 2014. Consultado el 15 de agosto de 2014 .
- ↑ "Glosario — Documentación de Python 3.9.2" . docs.python.org . Consultado el 23 de marzo de 2021 .
- ↑ EAFP Archivado el 26/10/2012 en Wayback Machine , Glosario de Python
- ↑ Hamblen, Diane. "Solo los límites de nuestra imaginación: una entrevista exclusiva con la Contralmirante Grace M. Hopper" . Revista de Tecnología de la Información del Departamento de la Marina. Archivado del original el 14 de enero de 2009. Consultado el 31 de enero de 2007 .
- 1 2 Python en pocas palabras, Alex Martelli , pág. 134
- ↑ LBYL Archivado el 21/01/2018 en Wayback Machine , Glosario de Python
- ↑ Alex Martelli (19 de mayo de 2003). "EAFP v. LBYL" . Lista de correo python-list . Consultado el 18 de julio de 2011 .
{{cite web}}: CS1 maint: servicio de archivado obsoleto ( enlace ) - ↑ "PEP 8 -- Guía de estilo para código Python" . Python.org . Consultado el 23 de marzo de 2021 .
- ↑ "Decoradores de Python 2.4: Reduciendo la duplicación de código y consolidando el conocimiento" . Dr. Dobb's . 1 de mayo de 2005. Archivado del original el 6 de febrero de 2007. Consultado el 8 de febrero de 2007 .
- ↑ "Nuevo decorador de recursión de cola" . ASPN: Python Cookbook . 14 de noviembre de 2006. Archivado del original el 9 de febrero de 2007. Consultado el 8 de febrero de 2007 .
- ↑ "El módulo decorador" . Archivado del original el 10 de febrero de 2007. Consultado el 8 de febrero de 2007 .
- ↑ cpython: El lenguaje de programación Python , Python, 15/10/2017, archivado del original el 15/09/2017 , consultado el 15/10/2017.
- ↑ "Otro tesoro escondido. · python/cpython@b1614a7" . GitHub . Consultado el 15-10-2017 .
Enlaces externos
- "La referencia del lenguaje Python" .
- Van Rossum, Guido . "El tutorial de Python" .(escrito por el autor de Python)
- Ramalho, Luciano (abril de 2022). Python fluido, segunda edición . O'Reilly Media, Inc. ISBN 9781492056355.
- sintaxis del lenguaje de programación
- Python (lenguaje de programación)