Sintaxis y semántica de Python

format_list_bulleted Contenido keyboard_arrow_down
ImprimirCitar
Un fragmento de código Python con palabras clave resaltadas en negrita fuente amarilla

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 los lectores humanos). El lenguaje Python tiene muchas similitudes con Perl, C y Java. Sin embargo, existen algunas diferencias claras entre los lenguajes. Admite múltiples paradigmas de programación, incluida la programación estructurada y orientada a objetos y la programación funcional, y cuenta con un sistema de tipos dinámico y una gestión automática de la memoria.

La sintaxis de Python es simple y consistente, y se adhiere al principio de que "debe haber una sola forma obvia de hacerlo", preferiblemente. El lenguaje incorpora estructuras y tipos de datos 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 utilizan puntuación, lo que contribuye a su diseño visual despejado.

El lenguaje proporciona un manejo sólido de errores a través de excepciones e incluye un depurador en la biblioteca estándar para una resolución eficiente de problemas. La sintaxis de Python, diseñada para facilitar su lectura y uso, lo convierte en una opción popular tanto entre principiantes como profesionales.

Filosofía diseño

Python fue diseñado para ser un lenguaje muy legible. Tiene un diseño visual relativamente ordenado y utiliza palabras clave en inglés con frecuencia, mientras que otros lenguajes utilizan signos de puntuación. Python apunta a ser simple y consistente en el diseño de su sintaxis, encapsulado en el mantra "Debería haber una -y preferiblemente solo una- manera obvia de hacerlo", del Zen de Python.

Este mantra se opone deliberadamente al mantra de Perl y Ruby: "hay más de una manera de hacerlo".

Palabras clave

Python tiene 35 palabras clave o palabras reservadas; no se pueden utilizar como identificadores.

  • and
  • as
  • assert
  • async
  • await
  • break
  • class
  • continue
  • def
  • del
  • elif
  • else
  • except
  • False
  • finally
  • for
  • from
  • global
  • if
  • import
  • in
  • is
  • lambda
  • None
  • nonlocal
  • not
  • or
  • pass
  • raise
  • return
  • True
  • try
  • while
  • with
  • yield

Además, Python también tiene 3 palabras clave blandas. A diferencia de las palabras clave duras habituales, las palabras clave blandas son palabras reservadas solo en los contextos limitados en los que interpretarlas como palabras clave tendría sentido sintáctico. Estas palabras se pueden usar como identificadores en otros lugares; puedes definir una función o variable denominada match o case.

  • _
  • case
  • match
Notas
  1. ^ a b async y await fueron introducidos en Python 3.5.
  2. ^ a b True y False se convirtió en palabras clave en Python 3.0. Anteriormente eran variables globales.
  3. ^ nonlocal fue introducido en Python 3.0.
  4. ^ a b c match, case y _ fueron introducidos como palabras clave en Python 3.10.

Indentación

Python utiliza espacios en blanco para delimitar bloques de flujo de control (siguiendo la regla del lado opuesto). Python toma prestada esta característica de su predecesor ABC: en lugar de puntuación o palabras clave, utiliza sangría para indicar la ejecución 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 separan con llaves ({ }) o palabras clave. En la mayoría de las convenciones de codificación para estos lenguajes, los programadores suelen sangrar el código dentro de un bloque para diferenciarlo visualmente del código circundante.

Una función recursiva llamada foo, a la que se le pasa un único parámetro, x, y si el parámetro es 0 llamará a una función diferente llamada bar y, de lo contrario, llamará a baz, pasando x, y también se llamará a sí misma recursivamente, pasando x-1 como parámetro, podría implementarse de esta manera en Python:

def Foo()x): si x == 0: bar() más: baz()x) Foo()x - 1)

y podría escribirse así en C con el estilo de sangría K&R:

vacío Foo()int x){} si ()x == 0) {} bar(); } más {} baz()x); Foo()x - 1); }}

El código con sangría incorrecta podría ser malinterpretado por un lector humano de manera diferente a como lo sería interpretado por 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 fue sangrada por error para que estuviera fuera del bloque if/else:

def Foo()x): si x == 0: bar() más: baz()x) Foo()x - 1)

haría que la última línea se ejecutara siempre, incluso cuando x sea 0, lo que daría como resultado una recursión sin fin.

Si bien tanto los espacios como los caracteres de tabulación se aceptan como formas de sangría y se puede utilizar cualquier múltiplo de espacios, se recomiendan los espacios y se recomiendan 4 espacios (como en los ejemplos anteriores) y son, por lejos, los más utilizados. Mezclar espacios y tabulaciones en líneas consecutivas no está permitido a partir de Python 3 porque eso puede generar errores que son difíciles de detectar, 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, son los que llevan la información de tipo. Todas las variables en Python contienen referencias a objetos, y estas referencias se pasan a funciones. Algunas personas (incluido el propio Guido van Rossum) han llamado a este esquema de paso de parámetros "llamada por referencia de objeto". Una referencia de objeto significa un nombre, y la referencia pasada es un "alias", es decir, una copia de la referencia al mismo objeto, tal como en C/C++. El valor del objeto puede cambiarse en la función llamada con el "alias", por ejemplo:

, titulado alist = ['a', 'b ', 'c '], titulado def my_func()al):...  al.apéndice()'x ')...  impresión()al)..., titulado my_func()alist)['a', 'b', 'c', 'x'], titulado alist['a', 'b', 'c', 'x']

La función my_func cambia el valor de alist con el argumento formal al, que es un alias de alist. 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.

, titulado alist = ['a', 'b ', 'c '], titulado def my_func()al):...  # al.append('x')...  al = al + ['x '] # a new list created and assigned to al means al is no more alias for alist...  impresión()al)..., titulado my_func()alist)['a', 'b', 'c', 'x'], titulado impresión()alist)['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 es moderadamente controlado por tipos. La conversión implícita está definida para tipos numéricos (así como para booleanos), por lo que se puede multiplicar de forma válida un número complejo por un entero (por ejemplo) sin 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 de base

Python tiene una amplia gama de tipos de datos básicos. Además de la aritmética convencional de números enteros y de punto flotante, admite de manera transparente la aritmética de precisión arbitraria, los números complejos y los números decimales.

Python admite una amplia variedad de operaciones con cadenas. Las cadenas en Python son inmutables, por lo que una operación con cadenas como la sustitución de caracteres, que en otros lenguajes de programación podría alterar la cadena en su lugar, devuelve una nueva cadena en Python. Las consideraciones de rendimiento a veces obligan a utilizar técnicas especiales en programas que modifican cadenas de forma intensiva, como unir matrices de caracteres en cadenas solo cuando es necesario.

Tipos de colección

Uno de los aspectos muy ú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 una manera que se puede referenciar o indexar fácilmente. Las colecciones vienen en dos formas básicas: secuencias y mapeos.

Los tipos secuenciales ordenados son listas (matrices dinámicas), tuplas y cadenas. Todas las secuencias están indexadas posicionalmente (de 0 a 1) y todas, excepto las cadenas, pueden contener cualquier tipo de objeto, incluidos 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 (ver más abajo). Las listas, por otro lado, son mutables; los elementos se pueden insertar, eliminar, modificar, agregar u ordenar en el lugar.

Por otro lado, las asignaciones son tipos (a menudo desordenados) implementados en forma de diccionarios que "asignan" un conjunto de claves inmutables a los elementos correspondientes (de forma muy similar a una función matemática). Por ejemplo, se podría definir un diccionario que tenga una cadena "toast" asignada al entero 42 o viceversa. Las claves de un diccionario deben ser de un tipo Python inmutable, como un entero o una cadena, porque en el fondo se implementan a través de una función hash. Esto permite tiempos de búsqueda mucho más rápidos, pero requiere que las claves no cambien.

Los diccionarios son fundamentales para el funcionamiento interno de Python, ya que residen en el núcleo de todos los objetos y clases: las asignaciones entre los nombres de las variables (cadenas) y los valores a los que hacen referencia los nombres se almacenan como diccionarios (consulte Sistema de objetos). Dado que estos diccionarios son directamente accesibles (a través del atributo __dict__ de un objeto), la metaprogramación es 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: set y frozenset, la única diferencia es que set es mutable y frozenset es inmutable. Los elementos de un conjunto deben ser hashables. Por lo tanto, por ejemplo, un frozenset puede ser un elemento de un set regular, mientras que lo opuesto no es cierto.

Python también ofrece amplias capacidades de manipulación de colecciones, como verificación de contención incorporada 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 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 de 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 llamado __add__ en una clase permite utilizar el operador + en objetos de esa clase.

Literales

Pendientes

Python tiene varios tipos de literales de cadena.

literales de cuerda normal

Se pueden utilizar comillas simples o dobles para citar 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 manera 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), utilizando el método format o el antiguo operador de formato de cadena %.

Por ejemplo, todas estas declaraciones de Python:

impresión()fAcabo de imprimir {}num} páginas a la impresora {}impresora}")impresión()Acabo de imprimir {} páginas a la impresora {}".formato()num, impresora)impresión()Acabo de imprimir {0} páginas a la impresora {1}".formato()num, impresora)impresión()Acabo de imprimir {num} páginas a la impresora {printer}".formato()num=num, impresora=impresora)impresión()Acabo de imprimir %s páginas a la impresora %s" % ()num, impresora)impresión()Acabo de imprimir %(num)s páginas a la impresora %(printer)s" % {}"num": num, "printer": impresora})

son equivalentes a la declaración de Perl:

impresión "Sólo imprimí páginas de $num a la impresora $printer\n"

Construyen una cadena usando las variables num y printer.

literales de cadena multilínea

También existen cadenas de varias líneas que comienzan y terminan con una serie de tres comillas simples o dobles y funcionan como estos documentos en Perl y Ruby.

Un ejemplo sencillo con interpolación de variables (utilizando el método format) es:

impresión()"Querido" {recipiente},Deseo que te vayas de Sunnydale y nunca vuelvas.No es un amor,{Sender}' '.formato()sender="Buffy the Vampire Slayer", beneficiario="Spike")

Cuerdas crudas

Por último, todos los tipos de cadenas mencionados anteriormente vienen en variedades "en bruto" (indicadas colocando una r literal antes de la comilla de apertura), que no interpolan con barras invertidas y, por lo tanto, son muy útiles para expresiones regulares; compare las "comillas @" en C#. Las cadenas en bruto se incluyeron originalmente específicamente para expresiones regulares. Debido a las limitaciones del tokenizador, las cadenas en bruto pueden no tener una barra invertida final. Crear una cadena en bruto que contenga una ruta de Windows que termine con una barra invertida requiere alguna variedad de soluciones alternativas (comúnmente, usar barras diagonales en lugar de barras invertidas, ya que Windows acepta ambas).

Algunos ejemplos incluyen:

, titulado # Un camino de Windows, incluso las cuerdas crudas no pueden terminar en una barra de atrás, titulado r"C:\Foo\Bar\Baz\"Archivo "Seguido", línea 1 r"C:\Foo\Bar\Baz\" ^SyntaxError: EOL mientras escanea la cadena literal, titulado dos_path = r"C:\Foo\Bar\Baz" # evita el error añadiendo, titulado dos_path.rstrip() # and removing trailing space'C:\Foo\\\Bar\\\Baz\\\ ', titulado citado_dos_path = r'{}".formato()dos_path), titulado citado_dos_path'C: 'Foo\\Bar\\Baz\', titulado # Una expresión regular que coincide con una cadena citada con posible retracción de la barra, titulado re.partido()r"([^]\\]\\.)*) ', citado_dos_path).grupo()1).rstrip()'C:\Foo\\\Bar\\\Baz\\\ ', titulado código = 'foo(2, bar) ', titulado # Invierta los argumentos en una llamada de dos brazos, titulado re.sub()r'\([^,]*?),([^]*)\) ', r'(\2, \1)', código)'foo(2, bar) ', titulado # Tenga en cuenta que esto no funcionará si cualquiera de los argumentos tiene parens o comas en él.

Concatenación de literales de cuerda adyacente

Se permiten cadenas literales (que posiblemente utilicen diferentes convenciones de comillas) que aparecen de forma contigua y solo separadas por espacios en blanco (incluidas las nuevas líneas) y se agregan en una única cadena más larga. Por lo tanto

Título = "Un buen giro: " \
 'Una historia natural del destornillador y el tornillo'

es equivalente a

Título = "Un buen giro: 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 = "Magnífico" # Hola en griegoimpresión()s)

Números

Los literales numéricos en Python son del tipo normal, p. ej., 0, -1, 3.4, 3.5e-8.

Python tiene números enteros de longitud arbitraria y aumenta automáticamente su tamaño de almacenamiento según sea necesario. Antes de Python 3, había dos tipos de números enteros: los números enteros tradicionales de tamaño fijo y los números enteros "largos" de tamaño arbitrario. La conversión a números enteros "largos" se realizaba automáticamente cuando era necesario y, por lo tanto, el programador generalmente no tenía que estar al tanto de los dos tipos de números enteros. En las versiones más nuevas del lenguaje, la distinción ha desaparecido por completo y todos los números enteros se comportan como números enteros de longitud arbitraria.

Python admite números de punto flotante normales, que se crean cuando se utiliza un punto en un literal (p. ej., 1.1), cuando se utilizan un entero y un número de punto flotante en una expresión o como resultado de algunas operaciones matemáticas ("división verdadera" mediante el operador / o exponenciación con un exponente negativo).

Python también admite números complejos de forma nativa. Los números complejos se indican con el sufijo J o j, p. ej., 3 + 4j.

Listas, tuplas, conjuntos, diccionarios

Python tiene 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

a_list = [1, 2, 3, "un perro"]

o utilizando la creación de objetos normal

a_second_list = []a_second_list.apéndice()4)a_second_list.apéndice()5)

Las tuplas (clase tuple) son secuencias inmutables de elementos de tipos arbitrarios. También existe una sintaxis especial para crear tuplas

a_tuple = 1, 2, 3, "cuatro"a_tuple = ()1, 2, 3, "cuatro")

Aunque las tuplas se crean separando los elementos con comas, la estructura completa suele estar entre paréntesis para facilitar su lectura. Una tupla vacía se denota con (), mientras que una tupla con un único valor se puede crear con (1,).

Los conjuntos (clase set) son contenedores mutables de elementos que se pueden convertir en hashes de tipos arbitrarios, sin duplicados. Los elementos no están ordenados, pero los conjuntos admiten la iteración sobre los elementos. La sintaxis para la creación de conjuntos utiliza llaves.

algunos_set = {}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 incluye una clase frozenset para conjuntos inmutables, consulte Tipos de colección.

Los diccionarios (clase dict) son asignaciones mutables que vinculan claves y valores correspondientes. Python tiene una sintaxis especial para crear diccionarios ({key: value})

a_diccionario = {}"key 1": "valor 1", 2: 3, 4: []

La sintaxis del diccionario es similar a la sintaxis del conjunto, la diferencia es la presencia de dos puntos. El literal vacío {} genera un diccionario vacío en lugar de un conjunto vacío, que se crea utilizando el constructor no literal: set().

Operadores

Arithmetic

Python incluye los operadores +, -, *, / ("división verdadera"), // (división de base), % (módulo) y ** (exponenciación), con su precedencia matemática habitual.

En Python 3, x / y realiza una "división verdadera", lo que significa que siempre devuelve un número flotante, incluso si tanto x como y son números enteros que se dividen de manera uniforme.

, titulado 4 / 22.0

y // realiza una división entera o una división de base, devolviendo la base del cociente como un 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 / y realizaba una división de números enteros y devolvía un valor de punto flotante solo si alguna de las entradas era un valor de punto flotante. Sin embargo, como Python es un lenguaje de tipado dinámico, no siempre era posible saber qué operación se estaba realizando, lo que a menudo generaba errores sutiles, lo que provocó 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, in y not in se utilizan en todo tipo de valores. Se pueden comparar números, cadenas, secuencias y asignaciones. En Python 3, los tipos dispares (como un str y un int) no tienen un orden relativo consistente, y los intentos de comparar estos tipos generan una excepción TypeError. 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 a < b < c tienen aproximadamente el mismo significado que tienen 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 un veredicto sea claro: si a < b es falso, c nunca se evalúa ya que la expresión ya no puede ser verdadera.

Para expresiones sin efectos secundarios, a < b < c es equivalente a a < b y b < c. Sin embargo, existe una diferencia sustancial cuando las expresiones tienen efectos secundarios. a < f(x) < b evaluará f(x) exactamente una vez, mientras que a < f(x) y f(x) < b lo evaluarán dos veces si el valor de a es 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 los valores vacíos como "", 0, None, 0.0, [] y {} como falsos, mientras que en general tratan los valores no vacíos o distintos de cero como verdaderos. Los valores booleanos True y False se agregaron al lenguaje en Python 2.2.1 como constantes (subclasificadas de 1 y 0) y se cambiaron para que sean palabras clave completas en Python 3. Los operadores de comparación binaria como == y > devuelven True o False.

Los operadores booleanos and y or utilizan una evaluación mínima. Por ejemplo, y == 0 or x/y > 100 nunca generará una excepción de división por cero. Estos operadores devuelven el valor del último operando evaluado, en lugar de True o False. Por lo tanto, la expresión (4 and 5) se evalúa como 5, y (4 or 5) se evalúa como 4.

Programación funcional

Como se mencionó anteriormente, otra fortaleza de Python es la disponibilidad de un estilo de programación funcional. Como es de esperar, esto hace que trabajar con listas y otras colecciones sea mucho más sencillo.

Comprensiones

Una de estas construcciones es la comprensión de listas, que se puede expresar con el siguiente formato:

L = [mapping_expression para elemento dentro source_list si filter_expresión]

Usando la comprensión de listas para calcular las primeras cinco potencias de dos:

poderes_de_dos = [2#n para n dentro rango()1, 6)

El algoritmo Quicksort se puede expresar de manera elegante (aunque ineficiente) mediante listas por comprensión:

def qsort()L): si L == []: Regreso [] pivote = L[0] Regreso ()qsort[x para x dentro L[1: si x c) pivote]) + [pivote] + qsort[x para x dentro L[1: si x >= pivote])

Python 2.7+ también admite la comprensión de conjuntos y la comprensión de diccionarios.

Funciones de primera clase

En Python, las funciones son objetos de primera clase que se pueden crear y pasar de forma dinámica.

La compatibilidad limitada de Python con funciones anónimas es la construcción lambda. Un ejemplo es la función anónima que eleva al cuadrado su entrada, llamada con el argumento 5:

f = lambda x: x#2f()5)

Las lambdas se limitan a contener una expresión en lugar de declaraciones, aunque el flujo de control todavía se puede implementar de forma menos elegante dentro de las lambdas mediante el uso de cortocircuitos y de forma más idiomática con expresiones condicionales.

Clausuras

Python admite cierres léxicos desde la versión 2.2. A continuación, se muestra un ejemplo de función que devuelve una función que se aproxima a la derivada de la función dada:

def derivados()f, dx): ""Retorna una función que aproxima el derivado de f usando un intervalo de dx, que debe ser apropiadamente pequeño. " def función()x): Regreso ()f()x + dx) - f()x) / dx Regreso función

Sin embargo, la sintaxis de Python a veces lleva a los programadores de otros lenguajes a pensar que los cierres no son compatibles. El alcance de las variables en Python está determinado implícitamente por el alcance en el que se asigna un valor a la variable, a menos que el alcance se declare explícitamente con global o nonlocal.

Tenga en cuenta que la vinculación de un nombre a un valor no es mutable desde dentro de la función. Dado:

, titulado def Foo()a, b):...  impresión()f'a: {}a}')...  impresión()f'b: {}b}')...  def bar()c):...  b = c...  impresión()fb* {}b}')...  bar()a)...  impresión()f'b: {}b}')... , titulado Foo()1, 2)a: 1b: 2b*: 1b: 2

y puedes ver que b, como se ve desde el alcance del cierre, conserva el valor que tenía; el enlace modificado de b dentro de la función interna no se propagó hacia afuera. La forma de evitar esto es usar una declaración nonlocal b en bar. En Python 2 (que carece de nonlocal), la solución alternativa 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 diferida de una función que, de otro modo, devolvería una lista con un espacio prohibitivo o que requiere un uso intensivo de recursos computacionales.

Este es un ejemplo para generar de forma diferida los números primos:

desde itertools importación Cuentadef genera_primes()stop_at=Ninguno): primos = [] para n dentro Cuenta()Empieza=2): si stop_at es no Ninguno y n  stop_at: Regreso # levanta la excepción de StopIteration compuesto = Falso para p dentro primos: si no n % p: compuesto = Cierto. descanso Elif p # 2  n: descanso si no compuesto: primos.apéndice()n) rendimiento n

Al llamar a esta función, el valor devuelto se puede iterar como si fuera una lista:

para i dentro genera_primes()100): # iterate over the primes between 0 and 100 impresión()i)para i dentro genera_primes(): # iterate over ALL primes indefinitely impresión()i)

La definición de un generador parece idéntica a la de una función, excepto que se utiliza la palabra clave yield en lugar de return. Sin embargo, un generador es un objeto con un estado persistente, que puede entrar y salir repetidamente del mismo ámbito. Una llamada a un generador se puede utilizar en lugar de una lista u otra estructura cuyos elementos se iterarán. Siempre que el bucle for del ejemplo requiere el siguiente elemento, se llama al generador y se obtiene el siguiente elemento.

Los generadores no tienen por qué ser infinitos como en el ejemplo anterior de los números primos. Cuando un generador termina, se genera una excepción interna que indica a cualquier contexto de llamada que ya no hay más valores. Entonces, terminará un bucle for u otra iteración.

Expresiones del generador

Las expresiones generadoras, introducidas en Python 2.4, son el equivalente de evaluación diferida de las comprensiones de listas. Si utilizamos el generador de números primos proporcionado en la sección anterior, podríamos definir una colección diferida, pero no del todo infinita.

desde itertools importación isliceprimes_under_million = ()i para i dentro genera_primes() si i c) 1000000)2_thousandth_prime = islice()primes_under_million, 1999, 2000).siguiente()

La mayor parte de la memoria y el tiempo necesarios para generar esta cantidad de números primos no se utilizarán hasta que se acceda realmente al elemento necesario. Lamentablemente, no se puede realizar una indexación y segmentación sencilla de los generadores, sino que se debe utilizar el módulo itertools o crear bucles propios. Por el contrario, una comprensión de listas es funcionalmente equivalente, pero es codiciosa a la hora de realizar todo el trabajo:

primes_under_million = [i para i dentro genera_primes()2000000) si i c) 1000000]2_thousandth_prime = primes_under_million[1999]

La comprensión de listas creará inmediatamente una lista grande (con 78498 elementos, en el ejemplo, pero creando transitoriamente una lista de números primos menores a dos millones), incluso si nunca se accede a la mayoría de los elementos. La comprensión de generadores es más parsimoniosa.

Diccionario y comprensión de conjunto

Si bien las listas y los generadores tenían comprensiones/expresiones, en versiones de Python anteriores a la 2.7 los otros tipos de colecciones integradas de Python (dictados y conjuntos) debían modificarse mediante listas o generadores:

, titulado dict(()n, n*n) para n dentro rango()5){}0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

Python 2.7 y 3.0 unificaron todos los tipos de colecciones al introducir la comprensión de diccionarios y conjuntos, de manera similar a la comprensión de listas:

, titulado [n*n para n dentro rango()5) # Comprensión de lista regular[0, 1, 4, 9, 16], titulado, titulado {}n*n para n dentro rango()5) # Comprensión de conjunto{}0, 1, 4, 9, 16}, titulado, titulado {}n: n*n para n dentro rango()5) # Dit comprehension{}0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

Objetos

Python es compatible con la mayoría de las técnicas de programación orientada a objetos (OOP). Permite el polimorfismo, no sólo dentro de una jerarquía de clases, sino también mediante tipado de pato. Cualquier objeto puede utilizarse para cualquier tipo, y funcionará siempre que tenga los métodos y atributos adecuados. Y todo en Python es un objeto, incluidas las clases, funciones, números y módulos. Python también es compatible con metaclases, una herramienta avanzada para mejorar la funcionalidad de las clases. Naturalmente, se admite la herencia, incluida la herencia múltiple. Python tiene un soporte muy limitado para las variables privadas mediante la manipulación de nombres, que rara vez se utiliza en la práctica, ya que el ocultamiento de información es visto por algunos como poco pitónico, ya que sugiere que la clase en cuestión contiene elementos internos poco estéticos o mal planificados. El eslogan "aquí todos somos usuarios responsables" se utiliza para describir esta actitud.

Como es cierto para los módulos, las clases en Python no ponen una barrera absoluta entre definición y usuario, sino que confían en la cortesía del usuario para no "romper la definición".

9. Clases, El pitón 2.6 Tutorial (2013)
Las doctrinas de POO, como el uso de métodos de acceso para leer miembros de datos, no se aplican en Python. Así como Python ofrece construcciones de programación funcional pero no intenta exigir transparencia referencial, ofrece un sistema de objetos pero no exige un comportamiento de POO. Además, siempre es posible redefinir la clase utilizando propiedades (ver Propiedades) de modo que cuando se establece o recupera una determinada variable en el código de llamada, en realidad invoque una llamada de función, de modo que spam.eggs = toast en realidad invoque spam.set_eggs(toast). Esto anula la ventaja práctica de las funciones de acceso y sigue siendo POO porque la propiedad eggs se convierte en una parte legítima de la interfaz del objeto: no necesita reflejar un detalle de implementación.

En la versión 2.2 de Python, se introdujeron las clases de "nuevo estilo". Con las clases de nuevo estilo, se unificaron los objetos y los tipos, lo que permitió la subclasificación de tipos. Incluso se pueden definir tipos completamente nuevos, con un comportamiento personalizado para los operadores infijos. Esto permite realizar muchas cosas radicales sintácticamente dentro de Python. También se adoptó un nuevo orden de resolución de métodos para la herencia múltiple con Python 2.3. También es posible ejecutar código personalizado al acceder o configurar atributos, aunque los detalles de esas técnicas han evolucionado entre las versiones de Python.

Con declaración

La declaración with maneja recursos y permite a los usuarios trabajar con el protocolo Context Manager. Se llama a una función (__enter__()) al ingresar al ámbito y a otra (__exit__()) al salir. Esto evita que se olvide liberar el recurso y también maneja situaciones más complicadas, como liberar el recurso cuando ocurre una excepción mientras está en uso. Los administradores de contexto se usan a menudo con archivos, conexiones de bases de datos, casos de prueba, etc.

Propiedades

Las propiedades permiten invocar métodos especialmente definidos en una instancia de objeto utilizando la misma sintaxis que se utiliza para el acceso a atributos. Un ejemplo de una clase que define algunas propiedades es:

clase MyClass: def __init_()auto): auto._a = Ninguno @property def a()auto): Regreso auto._a @a.Setter # hace que la propiedad sea ridícula def a()auto, valor): auto._a = valor

Descriptores

Se puede utilizar como descriptor una clase que define uno o más de los tres métodos especiales __get__(self, instance, owner), __set__(self, instance, value) y __delete__(self, instance). La creación de una instancia de un descriptor como miembro de una segunda clase convierte a la instancia en una propiedad de la segunda clase.

Métodos de clase y estática

Python permite la creación de métodos de clase y métodos estáticos mediante el uso de los decoradores @classmethod y @staticmethod. El primer argumento de un método de clase es el objeto de 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 clase se pasan a un método estático.

Excepciones

Python admite (y utiliza ampliamente) el manejo de excepciones como un medio para probar condiciones de error y otros eventos "excepcionales" en un programa.

El estilo de Python exige el uso de excepciones siempre que pueda surgir una condición de error. En lugar de probar el acceso a un archivo o recurso antes de usarlo, lo habitual en Python es simplemente intentar usarlo y capturar la excepción si se rechaza el acceso.

Las excepciones también se pueden utilizar 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 salirse de una lógica de manejo de mensajes profundamente anidada cuando se ha tomado la decisión de rechazar un mensaje o retenerlo para la aprobación del moderador.

Las excepciones se utilizan a menudo como una alternativa al bloque if, especialmente en situaciones con subprocesos. Un lema que se invoca con frecuencia es EAFP, o "Es más fácil pedir perdón que permiso", que se atribuye a Grace Hopper. La alternativa, conocida como LBYL, o "Mira antes de saltar", prueba explícitamente las condiciones previas.

En este primer ejemplo de código, siguiendo el enfoque LBYL, hay una verificación explícita del atributo antes del acceso:

si hasattr()spam, Huevos '): jamón = spam.huevosmás: handle_missing_attr()

Este segundo ejemplo sigue el paradigma EAFP:

Pruebe: jamón = spam.huevosSalvo AttributeError: handle_missing_attr()

Estos dos ejemplos de código tienen el mismo efecto, aunque habrá diferencias de rendimiento. Cuando spam tiene el atributo eggs, el ejemplo de EAFP se ejecutará más rápido. Cuando spam no tiene el atributo eggs (el caso "excepcional"), el ejemplo de EAFP se ejecutará más lento. El generador de perfiles de Python se puede utilizar en casos específicos para determinar las características de rendimiento. Si los casos excepcionales son poco frecuentes, la versión de EAFP tendrá un rendimiento promedio superior al de la alternativa. Además, evita toda la clase de vulnerabilidades de tiempo de verificación a tiempo de uso (TOCTTOU), otras condiciones de carrera y es compatible con el tipado de pato. Una desventaja de EAFP es que solo se puede utilizar con declaraciones; no se puede capturar una excepción en una expresión de generador, comprensión de lista o función lambda.

Comentarios y documentos

Python tiene dos formas de anotar el código Python. Una es mediante comentarios para indicar qué hace alguna parte del código. Los comentarios de una sola línea comienzan con el carácter numeral (#) 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 """ o ''' como delimitador en cada extremo) que no se usa en la asignación ni se evalúa de otro modo, sino que se ubica entre otras declaraciones.

Comentando un fragmento de código:

importación def getline(): Regreso .stdin.readlineación() # Obtener una línea y devolverla

Cómo comentar un fragmento de código con varias líneas:

def getline(): ""Esta función obtiene una línea y la devuelve. Como demostración, esta es una cadena multilínea. Esta cadena completa se puede acceder como getline.__doc__. " Regreso .stdin.readlineación()

Las cadenas de documentación (docstrings), es decir, cadenas que se encuentran solas sin asignación como la primera línea sangrada dentro de un módulo, clase, método o función, establecen automáticamente su contenido como un atributo llamado __doc__, que tiene como objetivo almacenar una descripción legible por humanos del propósito, comportamiento y uso del objeto. La función integrada help genera su salida en función de los atributos __doc__. Dichas cadenas se pueden delimitar con " o ' para cadenas de una sola línea, o pueden abarcar varias líneas si se delimitan 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 de varias.

Cadena de documentación de una sola línea:

def getline(): ""Consigue una línea de stdin y devuélvela."" Regreso .stdin.readlineación()

Cadena de documentación de varias líneas:

def getline(): "Consigue una línea" de stdin y devuélvelo. " Regreso .stdin.readlineación()

Las cadenas de documentación pueden ser tan largas como desee el programador y contener saltos de línea. A diferencia de los comentarios, las cadenas de documentación son en sí mismas objetos de Python y forman parte del código interpretado que Python ejecuta. Esto significa que un programa en ejecución puede recuperar sus propias cadenas de documentación y manipular esa información, pero el uso normal es brindarles a otros programadores información sobre cómo invocar el objeto que se documenta en la cadena de documentación.

Existen herramientas disponibles que pueden 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 función help(), o desde el shell con el comando pydoc pydoc.

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.

Anotaciones de funciones

Las anotaciones de funciones (tips) se definen en PEP 3107. Permiten adjuntar datos a los argumentos y al retorno de una función. El comportamiento de las anotaciones no está definido por el lenguaje y se deja en manos de marcos de trabajo de terceros. Por ejemplo, se podría escribir una biblioteca para manejar tipado estático:

def haul()Tema: Haulable, *vargs: PackAnimal) - No. Distancia

Decoradores

Un decorador es cualquier objeto Python que se pueda llamar y que se utilice para modificar una definición de función, método o clase. A un 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 sintaxis simple, y utiliza @ como palabra clave:

@viking_chorusdef menu_item(): impresión()"spam")

es equivalente a

def menu_item(): impresión()"spam")menu_item = viking_chorus()menu_item)

Los decoradores son una forma de metaprogramación; mejoran la acción de la función o el método que decoran. Por ejemplo, en el ejemplo siguiente, viking_chorus puede provocar que menu_item se ejecute 8 veces (consulte el esquema de Spam) cada vez que se lo llama:

def viking_chorus()myfunc): def interior_func()*args, #kwargs): para i dentro rango()8): myfunc()*args, #kwargs) Regreso interior_func

Los usos canónicos de los decoradores de funciones son la creación de métodos de clase o métodos estáticos, la adición de atributos de función, el seguimiento, la configuración de condiciones previas y posteriores y la sincronización, pero se pueden utilizar para mucho más, incluida la eliminación de la recursión de cola, la memorización e incluso la mejora de la escritura de otros decoradores.

Los decoradores se pueden encadenar colocando varios en líneas adyacentes:

@invincible@favourite_colour()"Blue")def black_knight(): paso

es equivalente a

def black_knight(): pasoblack_knight = invencible()favorite_colour()"Blue")black_knight)

o bien, utilizando variables intermedias

def black_knight(): pasoblue_decorator = favorite_colour()"Blue")decorada_by_blue = blue_decorator()black_knight)black_knight = invencible()decorada_by_blue)

En el ejemplo anterior, la fábrica de decoradores favourite_colour toma 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 favorite_colour()color): def decorator()func): def envoltura(): impresión()color) func() Regreso envoltura Regreso decorator

Esto decoraría entonces la función black_knight de modo que el color, "Azul", se imprimiría antes de que se ejecute la función black_knight. El cierre garantiza que el argumento de color sea accesible para la función contenedora más interna incluso cuando se devuelve y sale del ámbito, que es lo que permite que los decoradores funcionen.

A pesar del 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 que se añada funcionalidad a los objetos en tiempo de ejecución; los decoradores de Python añaden funcionalidad a las funciones y métodos en el momento de la definición y, por lo tanto, son una construcción de nivel superior a las clases con patrón decorador. El patrón decorador en sí mismo es trivialmente implementable en Python, porque el lenguaje tiene tipado pato y, por lo tanto, 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 ha sido solicitada en repetidas ocasiones y rechazada sistemáticamente por los desarrolladores principales. El intérprete de Python contiene un huevo de Pascua que resume los sentimientos de sus desarrolladores sobre este tema. El código from __future__ import braces genera la excepción SyntaxError: not a chance. El módulo __future__ se utiliza normalmente para proporcionar funciones 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 cuando se intenta importar este código.

El mensaje ¡Hola mundo! se imprime cuando se utiliza la declaración de importación import __hello__. En Python 2.7, en lugar de ¡Hola mundo!, se imprime Hola mundo....

Al importar el módulo antigravity se abre un navegador web en el cómic 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 funciones adicionales. En Python 3, este módulo también contiene una implementación del algoritmo "geohash", una referencia al cómic 426 de xkcd.

Referencias

  1. ^ "La lectura cuenta". - PEP 20 - El Zen de Python Archived 2014-12-05 en la máquina Wayback
  2. ^ "PEP 20 - El Zen de Python". Python Software Foundation. 2004-08-23. Archivado desde el original el 13 de diciembre de 2008. Retrieved 2008-11-24.
  3. ^ "2. Análisis Lexical". Python 3 documentación. Python Software Foundation. Retrieved 2021-03-11.
  4. ^ "2. Análisis Lexical". Python v2.7.18 documentación. Python Software Foundation. Retrieved 2021-03-11.
  5. ^ "Nuevas Palabras". Python v3.5 documentación. Docs.python.org. Archivado desde el original el 2016-06-18. Retrieved 2016-06-01.
  6. ^ "2. Análisis Lexical". Python 3 documentación. Python Software Foundation. Retrieved 2022-01-22.
  7. ^ "PEP 622 - Coincidencia de Patrón Estructural". 2020-06-23. Retrieved 2022-01-22.
  8. ^ "PEP 8 - Guía de estilo para el código del pitón". Python.org. Retrieved 2021-03-17.
  9. ^ Hoffa, Felipe (2017-07-26). Repositorios GitHub, 1 billón de archivos, 14 terabytes de código: Espacios o Tabs?". Mediana. Retrieved 2021-03-11.
  10. ^ "Tabs or Spaces". ukupat.github.io. Retrieved 2021-03-11.
  11. ^ "PEP 8 - Guía de estilo para el código del pitón". Python.org. Retrieved 2021-03-11.
  12. ^ "PEP 498 - Interpolación de cuerdas literarias". Lo nuevo en Python 3.62016-12-23. Archivado desde el original en 2017-03-30. Retrieved 2017-03-29.
  13. ^ "2. Análisis Lexical". Python v2.7.5 documentación. Docs.python.org. Archivado desde el original el 2012-10-23. Retrieved 2013-08-16.
  14. ^ "2. Análisis Lexical". Python v2.7.5 documentación. Docs.python.org. Archivado desde el original el 2012-10-23. Retrieved 2013-08-16.
  15. ^ Los elementos inmutables suelen ser inmutables, pero no necesariamente por definición. Véase python.org/3/glossary.htm
  16. ^ "6. Expresiones — documentación Python 3.9.2". docs.python.org. Retrieved 2021-03-17.
  17. ^ "Python 2.7.0 Release". Archivado desde el original en 2016-01-27. Retrieved 2016-01-19.
  18. ^ "5. Estructuras de datos — Python 2.7.18 documentación". Archivado desde el original en 2016-01-26. Retrieved 2016-01-19.
  19. ^ "5. Estructuras de datos — Python 2.7.18 documentación". Archivado desde el original en 2016-01-26. Retrieved 2016-01-19.
  20. ^ David Mertz. "Programación sindical en Python". IBM developer Funciona. Archivado desde el original el 2007-02-20. Retrieved 2007-08-27.
  21. ^ "PEP 308 - Expresiones condicionales". Archivado desde el original en 2016-03-13. Retrieved 2016-04-14.
  22. ^ El nonlocal keyword was adopted by PEP 3104 Archived 2014-12-02 at the Wayback Machine
  23. ^ "Python Style Guide". docs.python-guide.org. Archivado desde el original en 2015-03-09. Retrieved 2015-03-08.
  24. ^ "PEP 343... La declaración "con"". Archivado desde el original el 14 de diciembre de 2014. Retrieved 2014-08-15.
  25. ^ "Glosario — Python 3.9.2 documentación". docs.python.org. Retrieved 2021-03-23.
  26. ^ EAFP Archivado 2012-10-26 en la máquina Wayback, Glosario Python
  27. ^ Hamblen, Diane. "Sólo los límites de nuestra imaginación: una entrevista exclusiva con RADM Grace M. Hopper". Departamento de la revista Navy Information Technology. Archivado desde el original el 14 de enero de 2009. Retrieved 2007-01-31.
  28. ^ a b Python en pocas palabras, Alex Martelli, p. 134
  29. ^ LBYL Archived 2018-01-21 en el Wayback Machine, Python Glosario
  30. ^ Alex Martelli (19 de mayo de 2003). "EAFP v. LBYL". lista de correo de python-list. Archivado desde el original el 14 de julio de 2012. Retrieved 18 de julio 2011.
  31. ^ "PEP 8 - Guía de estilo para el código del pitón". Python.org. Retrieved 2021-03-23.
  32. ^ a b "PEP 3107 - Anotaciones de Función". Archivado desde el original en 2015-01-06. Retrieved 2014-08-15.
  33. ^ "Python 2.4 Decoradores: Reducción de la duplicación del código y consolidación del conocimiento". Dr. Dobb's2005-05-01. Archivado desde el original el 2007-02-06. Retrieved 2007-02-08.
  34. ^ "New Tail Recursion Decorator". ASPN: Python Cookbook2006-11-14. Archivado desde el original el 2007-02-09. Retrieved 2007-02-08.
  35. ^ "El módulo de decoración". Archivado desde el original en 2007-02-10. Retrieved 2007-02-08.
  36. ^ Cpython: El lenguaje de programación Python, Python, 2017-10-15, archivado desde el original en 2017-09-15, recuperado 2017-10-15
  37. ^ "Otro tesoro escondido. · python/cpython@b1614a7". GitHub. Retrieved 2017-10-15.
  • "La referencia del lenguaje pitón".
  • Van Rossum, Guido. "El Tutorial Python". (escrito por el autor de Python)
  • Ramalho, Luciano (abril 2022). Fluent Python, 2a edición. O'Reilly Media, Inc. ISBN 9781492056355.
Más resultados...
Tamaño del texto:
undoredo
format_boldformat_italicformat_underlinedstrikethrough_ssuperscriptsubscriptlink
save