De Wikipedia, la enciclopedia libre
Saltar a navegación Saltar a búsqueda

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 definidas entre los idiomas.

Filosofía del diseño [ editar ]

Python fue diseñado para ser un lenguaje altamente legible. [1] Tiene un diseño visual relativamente ordenado y usa palabras clave en inglés con frecuencia donde otros idiomas usan puntuación. Python pretende ser simple y consistente en el diseño de su sintaxis, encapsulado en el mantra "Debe haber una, y preferiblemente solo una, forma obvia de hacerlo" [ sic ], del Zen de Python . [2]

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

Palabras clave [ editar ]

Python tiene 35 palabras clave o palabras reservadas ; no se pueden utilizar como identificadores . [3] [4]

  • and
  • as
  • assert
  • async[nota 1]
  • await[nota 1]
  • break
  • class
  • continue
  • def
  • del
  • elif
  • else
  • except
  • False[nota 2]
  • finally
  • for
  • from
  • global
  • if
  • import
  • in
  • is
  • lambda
  • None
  • nonlocal[nota 3]
  • not
  • or
  • pass
  • raise
  • return
  • True[nota 2]
  • try
  • while
  • with
  • yield
Notas
  1. ^ Un b async y awaitse introdujeron en Python 3.5. [5]
  2. ^ a b True , se Falseconvirtieron en palabras clave en Python 3.0. Anteriormente eran variables globales.
  3. ^ nonlocal se introdujo en Python 3.0.


Sangría [ editar ]

Python usa espacios en blanco para delimitar los bloques de flujo de control (siguiendo la regla de fuera de juego ). Python toma prestada esta característica de su predecesor ABC : en lugar de puntuación o palabras clave, usa sangría para indicar la ejecución de un bloque .

En los llamados lenguajes de "formato libre", que utilizan la estructura de bloques derivada de ALGOL, los bloques de código se destacan con llaves ( { }) o palabras clave. En la mayoría de las convenciones de codificación para estos lenguajes, los programadores convencionalmente sangran el código dentro de un bloque, para diferenciarlo visualmente del código circundante.

Una función recursiva nombrada foo, a la que se le pasa un solo parámetro , xy si el parámetro es 0, llamará bary de lo bazcontrario se llamará qux, pasará xy también se llamará a sí misma recursivamente, pasando x-1como el parámetro podría implementarse así en Python:

def  foo ( x ):  si  x  ==  0 :  bar ()  baz ()  else :  qux ( x )  foo ( x  -  1 )

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

void  foo ( int  x ) {  if  ( x  ==  0 )  {  bar ();  baz ();  }  else  {  qux ( x );  foo ( x  -  1 );  } }

Python exige una convención que los programadores en lenguajes de estilo ALGOL suelen seguir.

El código sangrado incorrectamente podría ser mal leído por un lector humano de manera diferente a como lo interpretaría un compilador o un intérprete. Este ejemplo ilustra un error introducido por una sangría incorrecta:

def  foo ( x ):  si  x  ==  0 :  bar ()  baz ()  else :  qux ( x )  foo ( x  -  1 )

Aquí, en contraste con el fooejemplo anterior , la llamada foo(x - 1)a la función en la última línea tiene sangría errónea para estar fuera del bloque if/ else. Esto haría que siempre se ejecute, incluso cuando xsea ​​0, lo que resultará en una recursividad sin fin.

Si bien tanto el espacio como los caracteres de tabulación se aceptan como formas de sangría y se puede usar cualquier múltiplo de espacios, se recomiendan espacios [6] y 4 espacios (como en este artículo) se recomiendan y son, con mucho, los más utilizados. [7] [8] [ fuente no confiable? ] No se permite mezclar espacios y tabulaciones en líneas consecutivas en el mismo archivo de código fuente a partir de Python 3 [9] porque puede crear errores que son difíciles de ver, ya que muchas herramientas no distinguen visualmente espacios y tabulaciones.

Estructuras de datos [ editar ]

Dado que Python es un lenguaje escrito dinámicamente , los valores de Python , no las variables, llevan información de tipo. Esto tiene implicaciones para muchos aspectos del funcionamiento del lenguaje.

Todas las variables en Python contienen referencias a objetos, y estas referencias se pasan a funciones; una función no puede cambiar el valor de las referencias de variable en su función de llamada (pero consulte las excepciones a continuación). 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, como en C / C ++. El valor del objeto se puede cambiar en la función llamada con el "alias", por ejemplo:

>>> alist  =  [ 'a' ,  'b' ,  'c' ] >>> def  my_func ( al ): ...  al . append ( 'x' ) ...  de impresión ( al ) ... >>> mi_func ( alist ) [ 'a', 'b', 'c', 'x'] >>> alist [ 'a', ' b ',' c ',' x ']

La función my_funccambió el valor de alistcon el argumento formal al, que es un alias de alist. Sin embargo, cualquier intento de operar en el alias en sí no tendrá ningún efecto en el objeto original. [ aclaración necesaria ] En Python, los nombres accesibles no locales más internos y no declarados globales son todos alias.

Entre los lenguajes tipados dinámicamente, Python se revisa de forma moderada. La conversión implícita se define para tipos numéricos (así como booleanos), por lo que uno puede multiplicar válidamente 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 no válido para una función matemática que espera un número.

Tipos de base [ editar ]

Python tiene una amplia gama de tipos de datos básicos. Junto número entero convencional y de coma flotante aritmética, de forma transparente compatible con precisión arbitraria , números complejos , y los números de punto decimal flotante .

Python admite una amplia variedad de operaciones de cadenas. Las cadenas en Python son inmutables , por lo que una operación de cadena, como una 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 empujan a 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 [ editar ]

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 longitud - 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 candidatos perfectos para las claves de diccionario (ver más abajo). Las listas, por otro lado, son mutables; los elementos se pueden insertar, eliminar, modificar, agregar o ordenar in situ .

Los mapeos, por otro lado, son tipos (a menudo desordenados) implementados en forma de diccionarios que "mapean" un conjunto de claves inmutables a los elementos correspondientes (muy parecido a una función matemática). Por ejemplo, se podría definir un diccionario que tenga una cadena "toast"asignada al entero 42o viceversa. Las claves en un diccionario deben ser de un tipo de Python inmutable, como un número entero o una cadena, porque bajo el capó se implementan a través de una función hash . Esto hace que los tiempos de búsqueda sean 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 nombres de 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 __dict__atributo 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 teóricas de conjuntos como unión , intersección , diferencia , diferencia simétrica y pruebas de subconjuntos . Hay dos tipos de conjuntos: sety frozenset, la única diferencia es que setes mutable e frozensetinmutable. Los elementos de un conjunto deben ser mezclables. Así, por ejemplo, a frozensetpuede ser un elemento de un regular setmientras que lo contrario no es cierto.

Python también proporciona amplias capacidades de manipulación de colecciones, como la verificación de contención incorporada y un protocolo de iteración genérico.

Sistema de objetos [ editar ]

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 múltiples herencias y mixins .

El lenguaje admite una extensa introspección 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.

Los operadores se pueden sobrecargar en Python mediante la definición de funciones miembro especiales; por ejemplo, definir un método nombrado __add__en una clase permite usar el +operador en miembros de esa clase.

Literales [ editar ]

Cadenas [ editar ]

Python tiene varios tipos de cadenas literales .

Literales de cadena normales [ editar ]

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 las comillas dobles funcionan de manera idéntica, es decir, no hay interpolación de cadenas de expresiones $ foo . Sin embargo, la interpolación se puede hacer de varias formas: con "f-strings" (desde Python 3.6 [10] ), usando el formatmétodo o el antiguo operador % string-format.

Por ejemplo, la declaración de Perl:

print  "Acabo de imprimir $ num páginas en la impresora $ printer \ n"

es equivalente a cualquiera de estas declaraciones de Python:

imprimir ( f "Acabo de imprimir { num } páginas en la impresora { impresora } " )print ( "Acabo de imprimir {} páginas en la impresora {} " . formato ( num ,  impresora )) print ( "Acabo de imprimir {0} páginas en la impresora {1} " . formato ( num ,  impresora )) imprimir ( "Acabo de imprimir {num} páginas en la impresora {impresora} " . Formato ( num = num ,  impresora = impresora ))print ( "Acabo de imprimir % s páginas en la impresora % s "  %  ( num ,  printer )) print ( "Acabo de imprimir % (num) s páginas en la impresora % (printer) s "  %  { "num" :  num ,  "impresora" :  impresora })

Literales de cadena de varias líneas [ editar ]

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

Un ejemplo simple con interpolación de variables (usando el formatmétodo) es:

print ( "" "Estimado {destinatario} :Deseo que te vayas de Sunnydale y nunca regreses.No es amor, {sender}"" " . formato ( remitente = " Buffy la cazavampiros " ,  destinatario = " Spike " ))

Cuerdas sin procesar [ editar ]

Finalmente, todos los tipos de cadenas mencionados anteriormente vienen en variedades " crudas " (indicadas colocando una r literal antes de la cita de apertura), que no hacen interpolación de barra invertida y, por lo tanto, son muy útiles para expresiones regulares ; compare "@ -quoting" en C # . Las cadenas sin formato se incluyeron originalmente específicamente para expresiones regulares. Debido a las limitaciones del tokenizador, es posible que las cadenas sin formato no tengan una barra invertida al final. [11] La creación de una cadena sin formato que contenga una ruta de Windows que termine con una barra invertida requiere una variedad de soluciones alternativas (comúnmente, usar barras diagonales en lugar de barras invertidas, ya que Windows acepta ambas).

Ejemplos incluyen:

>>> # Una ruta de Windows, incluso las cadenas sin formato no pueden terminar en una barra invertida >>> r "C: \ Foo \ Bar \ Baz \" Archivo "<stdin>" , línea 1  r "C: \ Foo \ Bar \ Baz \ "  ^ SyntaxError : EOL mientras se escanea literal de cadena>>> dos_path  =  r "C: \ Foo \ Bar \ Baz \"  # evita el error agregando >>> dos_path . rstrip ()  # y eliminando el espacio final 'C: \\ Foo \\ Bar \\ Baz \\'>>> quoted_dos_path  =  r '" {} "' . format ( dos_path ) >>> quoted_dos_path '"C: \\ Foo \\ Bar \\ Baz \\"'>>> # Una expresión regular que coincide con una cadena entre comillas con posible barra invertida entre comillas >>> re . match ( r '"(([^" \\ ] | \\ .) *) "' ,  quoted_dos_path ) . group ( 1 ) . rstrip () 'C: \\ Foo \\ Bar \\ Baz \\'>>> código  =  'foo (2, bar)' >>> # Invierte los argumentos en una llamada de función de dos argumentos >>> re . sub ( r '\ (([^,] *?), ([^,] *?) \)' ,  r '(\ 2, \ 1)' ,  código ) 'foo (2, bar)' >> > # Tenga en cuenta que esto no funcionará si alguno de los argumentos tiene paréntesis o comas.

Concatenación de cadenas literales adyacentes [ editar ]

Los literales de cadena (utilizando posiblemente diferentes convenciones de comillas) que aparecen de forma contigua y solo separados por espacios en blanco (incluidas las nuevas líneas), están permitidos y se agregan en una sola cadena más larga. [12] Así

title  =  "One Good Turn:" \ 'Una historia natural del destornillador y el tornillo'

es equivalente a

title  =  "Un buen giro: Historia natural del destornillador y el tornillo"

Números [ editar ]

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

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

Python admite números de coma flotante normales , que se crean cuando se usa un punto en un literal (p 1.1. Ej. ), Cuando se usan un número entero y un número de coma 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 Jo j, p 3 + 4j. Ej .

Listas, tuplas, conjuntos, diccionarios [ editar ]

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 usando la creación de objetos normal

a_second_list  =  list () a_second_list . añadir ( 4 ) una_segunda_lista . añadir ( 5 )

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

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

Aunque las tuplas se crean separando elementos con comas, la construcción completa generalmente se incluye entre paréntesis para aumentar la legibilidad. Una tupla vacía se indica con ().

Los conjuntos (clase set) son contenedores mutables de elementos hash [13] 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

algún_conjunto  =  { 0 ,  (),  falso }

Los conjuntos de Python se parecen mucho a los conjuntos matemáticos y admiten operaciones como intersección y unión de conjuntos . Python también presenta una frozensetclase 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_dictionary  =  { "clave 1" :  "valor 1" ,  2 :  3 ,  4 :  []}

La sintaxis del diccionario es similar a la sintaxis establecida, la diferencia es la presencia de dos puntos. Los literales vacías {}resultados en un diccionario vacío en lugar de un conjunto vacío, que en cambio se ha creado usando el constructor no literal: set().

Operadores [ editar ]

Aritmética [ editar ]

Python incluye el +, -, *, /( "verdadero división"), //(división baja), %( módulo ), y **( exponenciación operadores), con su habitual precedencia matemática .

En Python 3, x / yrealiza una "división verdadera", lo que significa que siempre devuelve un flotante, incluso si ambos xy yson números enteros que se dividen uniformemente.

>>> 4  /  2 2,0

y //realiza la división de enteros o la división de piso , devolviendo el piso del cociente como un número entero.

En Python 2 (y la mayoría de los otros lenguajes de programación), a menos que se solicite explícitamente, x / ytambién realizó una división de enteros , devolviendo un flotante solo si cualquiera de las entradas era un flotante. Sin embargo, debido a que Python es un lenguaje de tipado dinámico, no siempre fue posible saber qué operación se estaba realizando, lo que a menudo conducía a 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 [ editar ]

Los operadores de comparación, es decir ==, !=, <, >, <=, >=, is, is not, iny not in[14] 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. Si bien era posible comparar si alguna cadena era mayor o menor que un número entero en Python 2, esto se consideró una peculiaridad de diseño histórica y finalmente se eliminó en Python 3.

Expresiones de comparación encadenadas como a < b < ctienen aproximadamente el 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 el veredicto sea 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) < bevaluará f(x)exactamente una vez, mientras que a < f(x) and f(x) < blo evaluará dos veces si el valor de aes menor que f(x)y una vez en caso contrario.

Operadores lógicos [ editar ]

En todas las versiones de Python, operadores booleanos tratan los valores cero o valores vacíos, tales como "", 0, None, 0.0, [], y {}como falso, mientras que en el tratamiento general de no vacíos, no los valores cero como verdadero. Los valores booleanos Truey Falsese agregaron al lenguaje en Python 2.2.1 como constantes (subclasificados de 1y 0) y se cambiaron para ser 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, y == 0 or x/y > 100nunca generará una excepción de división por cero. Estos operadores devuelven el valor del último operando evaluado, en lugar de Trueo False. Por lo tanto, la expresión se (4 and 5)evalúa 5y (4 or 5)evalúa 4.

Programación funcional [ editar ]

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

Comprensiones [ editar ]

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

L  =  [ mapping_expression  para  elemento  en  source_list  si  filter_expression ]

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

powers_of_two  =  [ 2 ** n  para  n  en el  rango ( 1 ,  6 )]

El algoritmo Quicksort se puede expresar con elegancia (aunque de manera ineficiente) utilizando listas por comprensión:

def  qsort ( L ):  si  L  ==  []:  return  []  pivote  =  L [ 0 ]  return  ( qsort ([ x  para  x  en  L [ 1 :]  si  x  <  pivote ])  +  [ pivote ]  +  qsort ([ x  para  x  en  L [ 1 :]  si  x  > =  pivote ]))

Python 2.7+ [15] también admite comprensiones de conjuntos [16] y comprensiones de diccionarios. [17]

Funciones de primera clase [ editar ]

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 de 5:

f  =  lambda  x :  x ** 2 f ( 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 lambda mediante el uso de cortocircuitos, [18] y de forma más idiomática con expresiones condicionales. [19]

Cierres [ editar ]

Python ha tenido soporte para cierres léxicos desde la versión 2.2. Aquí hay una función de ejemplo que devuelve una función que se aproxima a la derivada de la función dada:

def  derivada ( f ,  dx ):  "" "Devuelve una función que se aproxima a la derivada de f  usando un intervalo de dx, que debe ser apropiadamente pequeño.  " ""  def  función ( x ):  return  ( f ( x  +  dx )  -  función de retorno f ( x ))  /  dx  

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 la variable en Python está implícitamente determinado por el alcance en el que se asigna un valor a la variable, a menos que el alcance se declare explícitamente con globalo nonlocal. [20]

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

>>> def  foo ( a ,  b ): ...  print ( f 'a: { a } ' ) ...  print ( f 'b: { b } ' ) ...  def  bar ( c ): .. .  b  =  c ...  print ( f 'b *: { b } ' ) ...  barra ( a ) ...  print ( f'b: { b } ' ) ... >>> foo ( 1 ,  2 ) a: 1 b: 2 b *: 1 b: 2

y puede ver que b, como se ve desde el alcance del cierre, conserva el valor que tenía; la vinculación modificada del binterior de la función interior no se propagó hacia fuera. La forma de evitar esto es usar una nonlocal bdeclaración en bar. En Python 2 (que carece 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 [ editar ]

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 de espacio prohibitivo o computacionalmente intensiva.

Este es un ejemplo para generar perezosamente los números primos:

desde  itertools  import  countdef  generate_primes ( stop_at = Ninguno ):  primos  =  []  para  n  en el  conteo ( empiezan = 2 ):  si  stop_at  es  no  Ninguno  y  n  >  stop_at :  retorno  # plantea la excepción StopIteration  compuesta  =  False  para  p  en  números primos :  si  no  n  %  p :  compuesto  =  True  break  elif  p **  2  >  n :  romper  si  no  compuesto :  primos . añadir ( n )  rendimiento  n

Al llamar a esta función, el valor devuelto se puede iterar de forma muy similar a una lista:

para  i  en  generate_primes ( 100 ):  # iterar sobre los primos entre 0 y 100  print ( i )para  i  en  generate_primes ():  # iterar sobre TODOS los primos indefinidamente  print ( i )

La definición de un generador parece idéntica a la de una función, excepto que yieldse usa 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. Luego, se puede usar una llamada al 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 y genera el siguiente elemento.

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

Expresiones generadoras [ editar ]

Introducido en Python 2.4, las expresiones generadoras son el equivalente de evaluación perezosa de las listas por comprensión. 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.

desde  itertools  import  isliceprimes_under_million  =  ( i  para  i  en  generate_primes ()  si  i  <  1000000 ) two_thousandth_prime  =  islice ( primes_under_million ,  1999 ,  2000 ) . siguiente ()

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 puede realizar una indexación y división de generadores simples, pero debe usar el módulo itertools o "enrollar sus propios" bucles. Por el contrario, la comprensión de una lista es funcionalmente equivalente, pero es ávida en realizar todo el trabajo:

primes_under_million  =  [ i  para  i  en  generate_primes ( 2000000 )  si  i  <  1000000 ] two_thousandth_prime  =  primes_under_million [ 1999 ]

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

Diccionario y comprensiones de conjuntos [ editar ]

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 colección incorporados de Python (dictados y conjuntos) tenían que ser modificados para usar listas o generadores:

>>>  dictar (( n ,  n * n )  para  n  en el  rango ( 5 )) { 0 :  0 ,  1 :  1 ,  2 :  4 ,  3 :  9 ,  4 :  16 }

Python 2.7 y 3.0 unificaron todos los tipos de colecciones mediante la introducción de diccionarios y comprensiones de conjuntos, similares a las comprensiones de listas:

>>>  [ n * n  para  n  en  rango ( 5 )]  # comprensión de lista regular [ 0 ,  1 ,  4 ,  9 ,  16 ] >>> >>>  { n * n  para  n  en  rango ( 5 )}  # conjunto comprensión { 0 ,  1 ,  4 ,  9 ,  16 } >>> >>>  { n :  n *n  para  n  en el  rango ( 5 )}  # comprensión de dict { 0 :  0 ,  1 :  1 ,  2 :  4 ,  3 :  9 ,  4 :  16 }

Objetos [ editar ]

Python admite la mayoría de las técnicas de programación orientada a objetos (OOP). Permite el polimorfismo , no solo dentro de una jerarquía de clases, sino también mediante tipificación de pato . Cualquier objeto se puede utilizar para cualquier tipo y funcionará siempre que tenga los métodos y atributos adecuados. Y todo en Python es un objeto, incluidas clases, funciones, números y módulos. Python también tiene soporte para 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 variables privadas que utilizan la modificación de nombres, que rara vez se usa en la práctica para ocultar información.es visto por algunos como atípico , en el sentido de que sugiere que la clase en cuestión contiene elementos internos antiestéticos o mal planificados. El lema "aquí todos somos usuarios responsables" se utiliza para describir esta actitud. [21]

Como ocurre con los módulos, las clases en Python no ponen una barrera absoluta entre la definición y el usuario, sino que se basan en la cortesía del usuario para no "interrumpir la definición".

-  9. Clases , Tutorial de Python 2.6 (2013)

Las doctrinas de OOP , 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 comportamiento OOP . Además, siempre es posible redefinir la clase usando propiedades (ver Propiedades ) para que cuando una determinada variable se establezca o recupere en el código de llamada, realmente invoque una llamada de función, por lo que spam.eggs = toastrealmente podría invocar spam.set_eggs(toast). Esto anula la ventaja práctica de las funciones de acceso y sigue siendo OOP porque la propiedadeggs se convierte en una parte legítima de la interfaz del objeto: no es necesario que refleje un detalle de implementación.

En la versión 2.2 de Python, se introdujeron clases de "nuevo estilo". Con las clases de nuevo estilo, se unificaron objetos y tipos, lo que permitió la subclasificación de tipos. Incluso se pueden definir tipos completamente nuevos, completos con comportamiento personalizado para operadores infijos. Esto permite que se hagan 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 declaraciones [ editar ]

La withdeclaración maneja los recursos. [22] Se llama a una función al entrar en el ámbito y a otra al salir. Esto evita que se olvide de liberar el recurso y también maneja situaciones más complicadas como liberar el recurso cuando ocurre una excepción mientras está en uso.

Propiedades [ editar ]

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__ ( self ):  self . _a  =  Ninguno @property  def  a ( self ):  return  self . _a @a . setter  # hace que la propiedad se pueda escribir  def  a ( self ,  value ):  self . _a  =  valor

Descriptores [ editar ]

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)se puede utilizar como un descriptor. La creación de una instancia de un descriptor como miembro de una segunda clase hace que la instancia sea una propiedad de la segunda clase. [23]

Métodos de clase y estáticos [ editar ]

Python permite la creación de métodos de clase y métodos estáticos mediante el uso de decoradores@classmethod y . 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.@staticmethod

Excepciones [ editar ]

Python admite (y usa ampliamente) el manejo de excepciones como un medio para probar condiciones de error y otros eventos "excepcionales" en un programa. De hecho, incluso es posible atrapar la excepción causada por un error de sintaxis .

El estilo 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, es convencional en Python seguir adelante e intentar usarlo, detectando 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, usa excepciones para salir de la 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 if-block, especialmente en situaciones con subprocesos . Un lema comúnmente invocado es EAFP, o "Es más fácil pedir perdón que permiso", [24] que se atribuye a Grace Hopper . [25] [26] La alternativa, conocida como LBYL, o "Mira antes de saltar", prueba explícitamente las condiciones previas. [27]

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

if  hasattr ( spam ,  'huevos' ):  ham  =  spam . huevos más :  handle_missing_attr ()

Esta segunda muestra sigue el paradigma EAFP:

prueba :  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, la muestra EAFP se ejecutará más rápido. Cuando spamno tiene el atributo eggs(el caso "excepcional"), la muestra EAFP se ejecutará más lentamente. 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 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 , [26] [28] y es compatible con la tipificación de pato.. Un inconveniente de EAFP es que solo se puede usar con declaraciones; una excepción no se puede capturar en una expresión generadora, comprensión de lista o función lambda.

Comentarios y cadenas de documentos [ editar ]

Python tiene dos formas de anotar el código Python. Una es usar comentarios para indicar qué hace 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 """o '''como delimitador en cada extremo) que no se usa en la asignación ni se evalúa de otra manera, pero se encuentra entre otras declaraciones.

Comentar un fragmento de código:

importar  sysdef  getline ():  return  sys . stdin . readline ()  # Obtenga una línea y devuélvala

Comentar un fragmento de código con varias líneas:

def  getline ():  return  sys . stdin . readline ()  "" "esta función  obtiene una línea  y la devuelve" ""

Las cadenas de documentos (cadenas de documentación), es decir, las cadenas que se ubican solas sin asignación como la primera línea con sangría dentro de un módulo, clase, método o función, establecen automáticamente su contenido como un atributo nombrado __doc__, que está destinado a almacenar una descripción legible por humanos. del propósito, comportamiento y uso del objeto. La helpfunción incorporada genera su salida basada en __doc__atributos. Dichas cadenas se pueden delimitar con "o 'para cadenas de una sola línea, o pueden abarcar varias líneas si se delimitan con cualquiera de las dos """o '''cuál es la notación de Python para especificar cadenas de varias líneas. Sin embargo, la guía de estilo para el idioma especifica que """se prefieren las comillas dobles triples ( ) para cadenas de documentos de una o varias líneas. [29]

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

def  getline ():  "" "Obtenga una línea de stdin y devuélvala." ""  return  sys . stdin . readline ()

Cadena de documentación de varias líneas:

def  getline ():  "" "Obtenga una línea  de stdin  y devuélvala.  " ""  return  sys . stdin . readline ()

Las cadenas de documentos pueden ser tan grandes 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 ejecuta Python. Eso significa que un programa en ejecución puede recuperar sus propias cadenas de documentos y manipular esa información, pero el uso normal es dar a otros programadores información sobre cómo invocar el objeto que se documenta en la cadena de documentos.

Hay 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 Docstring desde el intérprete con la help()función, o desde el shell con el comando pydocpydoc .

El módulo estándar doctest usa interacciones copiadas de sesiones de shell de Python en cadenas de documentos para crear pruebas, mientras que el módulo docopt las usa para definir opciones de línea de comandos.

Anotaciones de funciones [ editar ]

Las anotaciones de funciones se definen en PEP 3107 . Permiten adjuntar datos a los argumentos y devolver una función. El comportamiento de las anotaciones no está definido por el lenguaje y se deja en manos de marcos de terceros. Por ejemplo, se podría escribir una biblioteca para manejar la escritura estática: [30]

def  haul ( item :  Haulable ,  * vargs :  PackAnimal )  ->  Distancia

Decoradores [ editar ]

Un decorador es cualquier objeto de Python invocable que se utiliza para modificar una función, método o definición de 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 azúcar sintáctica , usando @como palabra clave:

@viking_chorus def  menu_item ():  print ( "spam" )

es equivalente a

def  menu_item ():  print ( "spam" ) menu_item  =  viking_chorus ( menu_item )

Los decoradores son una forma de metaprogramación ; realzan la acción de la función o el método que decoran. Por ejemplo, en el ejemplo a continuación, viking_choruspodría causar menu_itemque se ejecute 8 veces (ver Boceto de correo no deseado ) cada vez que se llame:

def  coro_viking ( myfunc ):  def  inner_func ( * args ,  ** kwargs ):  for  i  in  range ( 8 ):  myfunc ( * args ,  ** kwargs )  return  inner_func

Usos canónicas de decoradores de función son para la creación de métodos de clase o métodos estáticos , añadiendo atributos de función, el rastreo , el establecimiento de pre- y postcondiciones , y sincronización , [31] , pero se pueden utilizar para mucho más, incluyendo la eliminación de la cola de recursión , [32] memoization y incluso mejorando la escritura de otros decoradores. [33]

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

@invincible @favourite_colour ( "Azul" ) def  black_knight ():  pasar

es equivalente a

def  caballero_negro ():  pass caballero_negro  =  invencible ( color_favorito ( "Azul" ) ( caballero_negro ))

o, usando variables intermedias

def  black_knight ():  pasar blue_decorator  =  favourite_colour ( "Blue" ) decorated_by_blue  =  blue_decorator ( black_knight ) black_knight  =  invencible ( decorated_by_blue )

En el ejemplo anterior, la fábrica defavourite_colour decoradores toma un argumento. Las fábricas de decoradores deben devolver un decorador, que luego se llama con el objeto a decorar como argumento:

def  favourite_colour ( color ):  def  decorator ( func ):  def  wrapper ():  print ( color )  func ()  return  wrapper  return  decorador

Esto luego decoraría la black_knightfunción de modo que el color "Blue",, se imprimiera antes de que se black_knightejecute la función. El cierre asegura que el argumento de color sea accesible para la función contenedora más interna incluso cuando se devuelve y sale del alcance, 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 de decorador es un patrón de diseño utilizado en lenguajes de programación orientados a objetos de tipo estático para permitir que se agregue funcionalidad a los objetos en tiempo de ejecución; Los decoradores de Python agregan funcionalidad a las funciones y métodos en el momento de la definición y, por lo tanto, son una construcción de mayor nivel que las clases de patrones de decoradores. El patrón del decorador en sí mismo se puede implementar de manera trivial en Python, porque el lenguaje es de tipo pato , por lo que generalmente no se considera como tal. [ aclaración necesaria ]

Huevos de Pascua [ editar ]

Los usuarios de lenguajes de corchetes , como C o Java , a veces esperan o desean que Python siga una convención de delimitadores de bloques. La sintaxis de bloques delimitados por llaves se ha solicitado repetidamente y los desarrolladores principales la han rechazado constantemente. El intérprete de Python contiene un easter egg que resume los sentimientos 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 cuando se intenta import this.

El mensaje Hello world!se imprime cuando import __hello__se utiliza la declaración de importación . En Python 2.7, en lugar de Hello world!imprime Hello world....

La importación del antigravitymódulo abre un navegador web a xkcd comic 353 que retrata un uso ficticio humorístico para dicho módulo, destinado a demostrar la facilidad con la que los módulos de Python permiten una funcionalidad adicional. [34] En Python 3, este módulo también contiene una implementación del algoritmo "geohash", una referencia a xkcd comic 426 . [35]

Referencias [ editar ]

  1. ^ "La legibilidad cuenta". - PEP 20 - The Zen of Python Archivado el 5 de diciembre de 2014 en la Wayback Machine.
  2. ^ "PEP 20 - El Zen de Python" . Fundación de software Python. 2004-08-23. Archivado desde el original el 3 de diciembre de 2008 . Consultado el 24 de noviembre de 2008 .
  3. ^ "2. Análisis léxico" . Documentación de Python 3 . Fundación de software Python . Consultado el 11 de marzo de 2021 .
  4. ^ "2. Análisis léxico" . Documentación de Python v2.7.18 . Fundación de software Python . Consultado el 11 de marzo de 2021 .
  5. ^ "Nuevas palabras clave" . Documentación de Python v3.5 . Docs.python.org. Archivado desde el original el 18 de junio de 2016 . Consultado el 1 de junio de 2016 .
  6. ^ "PEP 8 - Guía de estilo para código Python" . Python.org . Consultado el 17 de marzo de 2021 .
  7. Hoffa, Felipe (26 de julio de 2017). "400.000 repositorios de GitHub, mil millones de archivos, 14 terabytes de código: ¿espacios o pestañas?" . Medio . Consultado el 11 de marzo de 2021 .
  8. ^ "Pestañas o espacios" . ukupat.github.io . Consultado el 11 de marzo de 2021 .
  9. ^ "PEP 8 - Guía de estilo para código Python" . Python.org . Consultado el 11 de marzo de 2021 .
  10. ^ "PEP 498 - Interpolación de cadenas literal" . Novedades de Python 3.6 . 2016-12-23. Archivado desde el original el 30 de marzo de 2017 . Consultado el 29 de marzo de 2017 .
  11. ^ "2. Análisis léxico" . Documentación de Python v2.7.5 . Docs.python.org. Archivado desde el original el 23 de octubre de 2012 . Consultado el 16 de agosto de 2013 .
  12. ^ "2. Análisis léxico" . Documentación de Python v2.7.5 . Docs.python.org. Archivado desde el original el 23 de octubre de 2012 . Consultado el 16 de agosto de 2013 .
  13. ^ Los artículos lavables suelen ser inmutables, pero no necesariamente por definición. Ver python.org/3/glossary.htm
  14. ^ "6. Expresiones - Documentación de Python 3.9.2" . docs.python.org . Consultado el 17 de marzo de 2021 .
  15. ^ "Copia archivada" . Archivado desde el original el 27 de enero de 2016 . Consultado el 19 de enero de 2016 .Mantenimiento de CS1: copia archivada como título ( enlace )
  16. ^ "Copia archivada" . Archivado desde el original el 26 de enero de 2016 . Consultado el 19 de enero de 2016 .Mantenimiento de CS1: copia archivada como título ( enlace )
  17. ^ "Copia archivada" . Archivado desde el original el 26 de enero de 2016 . Consultado el 19 de enero de 2016 .Mantenimiento de CS1: copia archivada como título ( enlace )
  18. ^ David Mertz. "Programación funcional en Python" . IBM developerWorks. Archivado desde el original el 20 de febrero de 2007 . Consultado el 27 de agosto de 2007 .
  19. ^ "PEP 308 - Expresiones condicionales" . Archivado desde el original el 13 de marzo de 2016 . Consultado el 14 de abril de 2016 .
  20. ^ Lanonlocalpalabra clave fue adoptada por PEP 3104 Archivado 2014-12-02 en Wayback Machine.
  21. ^ "Guía de estilo de Python" . docs.python-guide.org. Archivado desde el original el 9 de marzo de 2015 . Consultado el 8 de marzo de 2015 .
  22. ^ "Copia archivada" . Archivado desde el original el 14 de diciembre de 2014 . Consultado el 15 de agosto de 2014 .Mantenimiento de CS1: copia archivada como título ( enlace )
  23. ^ "Glosario - Documentación de Python 3.9.2" . docs.python.org . Consultado el 23 de marzo de 2021 .
  24. ^ EAFP Archivado 2012-10-26 en Wayback Machine , Glosario de Python
  25. ^ Hamblen, Diane. "Sólo los límites de nuestra imaginación: una entrevista exclusiva con RADM Grace M. Hopper" . Revista de Tecnología de la Información del Departamento de la Marina. Archivado desde el original el 14 de enero de 2009 . Consultado el 31 de enero de 2007 .
  26. ↑ a b Python en pocas palabras, Alex Martelli , p. 134
  27. ^ LBYL Archivado 2018-01-21 en Wayback Machine , Glosario de Python
  28. ^ 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 . Consultado el 18 de julio de 2011 .
  29. ^ "PEP 8 - Guía de estilo para código Python" . Python.org . Consultado el 23 de marzo de 2021 .
  30. ^ "Copia archivada" . Archivado desde el original el 6 de enero de 2015 . Consultado el 15 de agosto de 2014 .Mantenimiento de CS1: copia archivada como título ( enlace )
  31. ^ "Decoradores de Python 2.4: Reducir la duplicación de código y consolidar el conocimiento" . Dr. Dobb's . 2005-05-01. Archivado desde el original el 6 de febrero de 2007 . Consultado el 8 de febrero de 2007 .
  32. ^ "Decorador de recursividad de cola nueva" . ASPN: Libro de cocina de Python . 2006-11-14. Archivado desde el original el 9 de febrero de 2007 . Consultado el 8 de febrero de 2007 .
  33. ^ "El módulo decorador" . Archivado desde el original el 10 de febrero de 2007 . Consultado el 8 de febrero de 2007 .
  34. ^ cpython: El lenguaje de programación Python , Python, 2017-10-15, archivado desde el original el 2017-09-15 , consultado el 2017-10-15
  35. ^ "Otro tesoro escondido. · Python / cpython @ b1614a7" . GitHub . Consultado el 15 de octubre de 2017 .

Enlaces externos [ editar ]

  • Tutorial de Python escrito por el autor de Python, Guido van Rossum.