Pregunta Funciones ocultas de Python [cerrado]


¿Cuáles son las características menos conocidas pero útiles del lenguaje de programación Python?

  • Intenta limitar las respuestas al núcleo de Python.
  • Una característica por respuesta.
  • Dé un ejemplo y una breve descripción de la característica, no solo un enlace a la documentación.
  • Etiquete la función usando un título como primera línea.

Enlaces rápidos a las respuestas:


1420


origen


Respuestas:


Encadenamiento de operadores de comparación:

>>> x = 5
>>> 1 < x < 10
True
>>> 10 < x < 20 
False
>>> x < 10 < x*10 < 100
True
>>> 10 > x <= 9
True
>>> 5 == x > 4
True

En caso de que estés pensando que está haciendo 1 < x, que sale como Truey luego comparando True < 10, cual es también True, entonces no, eso realmente no es lo que sucede (ver el último ejemplo). Realmente se está traduciendo en 1 < x and x < 10y x < 10 and 10 < x * 10 and x*10 < 100, pero con menos tipeo y cada término solo se evalúa una vez.


741



Obtenga el árbol de análisis sintáctico de python para depurar su expresión regular.

Las expresiones regulares son una gran característica de Python, pero depurarlas puede ser complicado, y es muy fácil obtener una expresión regular incorrecta.

Afortunadamente, Python puede imprimir el árbol de análisis sintáctico de expresiones regulares al pasar la bandera oculta, experimental e indocumentada re.DEBUG (en realidad, 128) a re.compile.

>>> re.compile("^\[font(?:=(?P<size>[-+][0-9]{1,2}))?\](.*?)[/font]",
    re.DEBUG)
at at_beginning
literal 91
literal 102
literal 111
literal 110
literal 116
max_repeat 0 1
  subpattern None
    literal 61
    subpattern 1
      in
        literal 45
        literal 43
      max_repeat 1 2
        in
          range (48, 57)
literal 93
subpattern 2
  min_repeat 0 65535
    any None
in
  literal 47
  literal 102
  literal 111
  literal 110
  literal 116

Una vez que comprenda la sintaxis, podrá detectar sus errores. Ahí podemos ver que olvidé escapar del [] en [/font].

Por supuesto, puedes combinarlo con las banderas que quieras, como expresiones regulares comentadas:

>>> re.compile("""
 ^              # start of a line
 \[font         # the font tag
 (?:=(?P<size>  # optional [font=+size]
 [-+][0-9]{1,2} # size specification
 ))?
 \]             # end of tag
 (.*?)          # text between the tags
 \[/font\]      # end of the tag
 """, re.DEBUG|re.VERBOSE|re.DOTALL)

512



enumerar

Ajustar un iterable con enumerate y arrojará el elemento junto con su índice.

Por ejemplo:


>>> a = ['a', 'b', 'c', 'd', 'e']
>>> for index, item in enumerate(a): print index, item
...
0 a
1 b
2 c
3 d
4 e
>>>

Referencias


460



Creando objetos generadores

Si tú escribes

x=(n for n in foo if bar(n))

puedes sacar el generador y asignarlo a x. Ahora significa que puedes hacer

for n in x:

La ventaja de esto es que no necesita almacenamiento intermedio, que necesitaría si lo hiciera

x = [n for n in foo if bar(n)]

En algunos casos esto puede conducir a una aceleración significativa.

Puede agregar muchas sentencias if al final del generador, básicamente replicando bucles anidados para:

>>> n = ((a,b) for a in range(0,2) for b in range(4,6))
>>> for i in n:
...   print i 

(0, 4)
(0, 5)
(1, 4)
(1, 5)

419



iter () puede tomar un argumento invocable

Por ejemplo:

def seek_next_line(f):
    for c in iter(lambda: f.read(1),'\n'):
        pass

los iter(callable, until_value) llamar repetidamente a la función callable y cede su resultado hasta until_value es regresado.


353



Tenga cuidado con los argumentos predeterminados mutables

>>> def foo(x=[]):
...     x.append(1)
...     print x
... 
>>> foo()
[1]
>>> foo()
[1, 1]
>>> foo()
[1, 1, 1]

En su lugar, debe usar un valor centinela que indique "no proporcionado" y reemplácelo con el mutable que desee de manera predeterminada:

>>> def foo(x=None):
...     if x is None:
...         x = []
...     x.append(1)
...     print x
>>> foo()
[1]
>>> foo()
[1]

339



Enviar valores a las funciones del generador. Por ejemplo tener esta función:

def mygen():
    """Yield 5 until something else is passed back via send()"""
    a = 5
    while True:
        f = (yield a) #yield a and possibly get f in return
        if f is not None: 
            a = f  #store the new value

Usted puede:

>>> g = mygen()
>>> g.next()
5
>>> g.next()
5
>>> g.send(7)  #we send this back to the generator
7
>>> g.next() #now it will yield 7 until we send something else
7

317



Si no le gusta usar espacios en blanco para indicar ámbitos, puede usar el estilo C {} al emitir:

from __future__ import braces

314