¿Para qué se usa __future__ en Python y cómo / cuándo usarlo, y cómo funciona?

806

__future__aparece con frecuencia en los módulos de Python. No entiendo para qué __future__sirve y cómo / cuándo usarlo, incluso después de leer el __future__documento de Python .

¿Alguien puede explicar con ejemplos?

Algunas respuestas con respecto al uso básico de __future__que he recibido parecían correctas.

Sin embargo, necesito entender una cosa más sobre cómo __future__funciona:

El concepto más confuso para mí es cómo una versión actual de Python incluye funciones para versiones futuras y cómo un programa que usa una función de una versión futura se puede compilar con éxito en la versión actual de Python.

Supongo que la versión actual incluye características potenciales para el futuro. Sin embargo, las funciones solo están disponibles mediante el uso __future__porque no son el estándar actual. Avísame si estoy en lo cierto.

3
  • 11
    Esta es la propuesta original para la declaración futura. Lo encontré útil para comprender por qué está allí en primer lugar y, por lo tanto, cuándo y cómo usarlo sigue naturalmente. python.org/dev/peps/pep-0236Jpaji Rajnish 2 mar 15 a las 3:49
  • 77
    Básicamente es el equivalente a "Supongo que no estás preparado para esto, pero a tus hijos les va a encantar" . Jean-François Corbett 16 de diciembre de 2016 a las 9:10
  • 6
    Una declaración futura es una directiva para el compilador de que un módulo en particular debe compilarse usando sintaxis o semántica que estará disponible en una versión futura específica de Python. La declaración futura tiene como objetivo facilitar la migración a futuras versiones de Python que introducen cambios incompatibles en el lenguaje. Permite el uso de las nuevas funciones por módulo antes del lanzamiento en el que la función se convierte en estándar. shivam13juna 27/11/18 a las 11:01
454

Con __future__la inclusión del módulo, puede acostumbrarse lentamente a cambios incompatibles o que introduzcan nuevas palabras clave.

Por ejemplo, para usar administradores de contexto, tenía que hacerlo from __future__ import with_statementen 2.5, ya que la withpalabra clave era nueva y ya no debería usarse como nombres de variables. Para usar withcomo palabra clave de Python en Python 2.5 o anterior, deberá usar la importación desde arriba.

Otro ejemplo es

from __future__ import division
print 8/7  # prints 1.1428571428571428
print 8//7 # prints 1

Sin el __future__material, ambas printdeclaraciones se imprimirían 1.

La diferencia interna es que sin esa importación, /se asigna al __div__()método, mientras que con él, __truediv__()se usa. (En cualquier caso, //llama __floordiv__().)

Apropos print: se printconvierte en una función en 3.x, perdiendo su propiedad especial como palabra clave. Entonces es al revés.

>>> print

>>> from __future__ import print_function
>>> print
<built-in function print>
>>>
10
  • 173
    no olvides from __future__ import braces: pmdeous 16 de agosto de 2011 a las 8:22
  • 14
    @zoogleflatt Si eres más un tipo de pestañas, no conoces PEP 8. Se recomienda encarecidamente no usar pestañas ...glglgl 3 mar.15 a las 19:29
  • 5
    @glglgl Bueno, técnicamente solo dice que son los preferidos. No estaba del todo claro para mí después de leer por qué esto es exactamente, supongo que es para que los niveles de sangría coincidan exactamente para hacer el código más ordenado. Jpaji Rajnish 6 mar.15 a las 7:03
  • 4
    @zoogleflatt Seguramente también tiene que ver con el hecho de que la mayoría de la gente usa 4 espacios para 1 nivel de sangría, que por razones de compatibilidad una pestaña equivale a 8 espacios y no se recomienda mezclar pestañas y espacios (resp., AFAIK, incluso no permitido en Py3)glglgl 6 de marzo de 2015 a las 8:45
  • 1
    @whiteSkar Actualmente no estoy actualizado con las versiones más nuevas de python 3, pero supongo que todavía está en uso, solo que probablemente no lo necesite con estas características bastante antiguas. En Python 3, printdefinitivamente es una función, pero puede haber otras características que podrían usar __future__. (Editar: consulte docs.python.org/3/library/__future__.html donde todavía se usa)glglgl 30 abr.20 a las 6:50
222

Cuando tu lo hagas

from __future__ import whatever

En realidad, no está utilizando una importdeclaración, sino una declaración futura . Está leyendo los documentos incorrectos, ya que en realidad no está importando ese módulo.

Las declaraciones futuras son especiales: cambian la forma en que se analiza su módulo de Python, por lo que deben estar en la parte superior del archivo. Dan un significado nuevo, o diferente, a las palabras o símbolos en su archivo. De los documentos:

A future statement is a directive to the compiler that a particular module should be compiled using syntax or semantics that will be available in a specified future release of Python. The future statement is intended to ease migration to future versions of Python that introduce incompatible changes to the language. It allows use of the new features on a per-module basis before the release in which the feature becomes standard.

Si realmente desea importar el __future__módulo, simplemente haga

import __future__

y luego acceda a él como de costumbre.

1
  • 5
    Técnicamente, también es una declaración de importación, ya que el nombre relevante está vinculado a una variable local. from __future__ import print_functionambos cambia el comportamiento de la printpalabra clave y tiene un efecto de tiempo de ejecución equivalente aprint_function = __import__("__future__").print_functionpppery 17 de julio de 2017 a las 1:19
128

__future__ es un pseudo-módulo que los programadores pueden utilizar para habilitar nuevas funciones de lenguaje que no son compatibles con el intérprete actual . Por ejemplo, la expresión 11/4actualmente se evalúa como 2. Si el módulo en el que se ejecuta hubiera habilitado la división verdadera ejecutando:

from __future__ import division

la expresión 11/4evaluaría a 2.75. Al importar el __future__módulo y evaluar sus variables, puede ver cuándo se agregó por primera vez una nueva característica al idioma y cuándo se convertirá en la predeterminada:

>>> import __future__
>>> __future__.division
_Feature((2, 2, 0, 'alpha', 2), (3, 0, 0, 'alpha', 0), 8192)
2
  • 1
    Entonces, según la versión de lanzamiento en las variables, si su intérprete está usando una versión posterior a la indicada, ¿no import __future__ xyzes una operación? Ray 15/04/2016 a las 15:15
  • 6
    Es algo análogo a un polyfill en el mundo de los navegadorescs01 2 de diciembre de 2016 a las 18:37
61

Se puede usar para usar funciones que aparecerán en versiones más recientes mientras tenga una versión anterior de Python.

Por ejemplo

>>> from __future__ import print_function

te permitirá usar printcomo función:

>>> print('# of entries', len(dictionary), file=sys.stderr)
0
58

Ya hay algunas respuestas excelentes, pero ninguna de ellas aborda una lista completa de lo que la __future__declaración admite actualmente.

En pocas palabras, la __future__declaración obliga a los intérpretes de Python a utilizar características más nuevas del lenguaje.


Las características que admite actualmente son las siguientes:

nested_scopes

Antes de Python 2.1, el siguiente código generaba un NameError :

def f():
    ...
    def g(value):
        ...
        return g(value-1) + 1
    ...

La from __future__ import nested_scopesdirectiva permitirá que esta función esté habilitada.

generators

Se introdujeron funciones de generador como la que se muestra a continuación para guardar el estado entre llamadas de función sucesivas:

def fib():
    a, b = 0, 1
    while 1:
       yield b
       a, b = b, a+b

division

La división clásica se usa en las versiones de Python 2.x. Lo que significa que algunas declaraciones de división devuelven una aproximación razonable de la división ("división verdadera") y otras devuelven el piso ("división del piso"). A partir de Python 3.0, la división verdadera se especifica mediante x/y, mientras que la división de piso se especifica mediante x//y.

La from __future__ import divisiondirectiva fuerza el uso de la división de estilo Python 3.0.

absolute_import

Permite que los paréntesis incluyan varias importdeclaraciones. Por ejemplo:

from Tkinter import (Tk, Frame, Button, Entry, Canvas, Text,
    LEFT, DISABLED, NORMAL, RIDGE, END)

En lugar de:

from Tkinter import Tk, Frame, Button, Entry, Canvas, Text, \
    LEFT, DISABLED, NORMAL, RIDGE, END

O:

from Tkinter import Tk, Frame, Button, Entry, Canvas, Text
from Tkinter import LEFT, DISABLED, NORMAL, RIDGE, END

with_statement

Agrega la declaración withcomo palabra clave en Python para eliminar la necesidad de try/finallydeclaraciones. Los usos comunes de esto son cuando se realizan E / S de archivos, como:

with open('workfile', 'r') as f:
     read_data = f.read()

print_function:

Fuerza el uso de la print()llamada a la función de estilo de paréntesis de Python 3 en lugar de la print MESSAGEdeclaración de estilo.

unicode_literals

Introduce la sintaxis literal del bytesobjeto. Lo que significa que declaraciones tales como bytes('Hello world', 'ascii')se pueden expresar simplemente como b'Hello world'.

generator_stop

Reemplaza el uso de la StopIterationexcepción utilizada dentro de las funciones del generador con la RuntimeErrorexcepción.

Otro uso no mencionado anteriormente es que la __future__declaración también requiere el uso de intérpretes de Python 2.1+, ya que el uso de una versión anterior generará una excepción de tiempo de ejecución.


Referencias

4
  • 2
    Suponiendo que está desconectado, ¿cómo sabe Python si hay una versión futura disponible o no? ¿Y cómo usa las funciones futuras si no ha instalado la versión futura de Python en su computadora? Mohsen Haddadi 9 de mayo de 2019 a las 7:57
  • 3
    @MohsenHaddadi La declaración de futuro es algo así como una marca de características ... Cuando se aceptan ciertas características en Python que cambian el comportamiento de los programas existentes (como la división verdadera, por ejemplo), primero puede habilitarlas con la declaración de futuro y luego, en una versión futura , se convierten en una característica permanente del idioma. De ahí el nombre __future__. Creo que esta capacidad de optar por romper los cambios temprano está destinada a ayudar a los programas existentes a hacer la transición de manera oportuna, antes de que el cambio radical entre en pleno efecto. Dev 20/06/20 a las 9:12
  • 1
    Creo que esta es la mejor respuesta. especialmente al comienzo de la respuesta, "forzar" a utilizar "funciones más nuevas". soMuchToLearnAndShare 5 nov.20 a las 10:21
  • 1
    Excelente respuesta, solo desearía que hubiera una from __past__ import printcomo realmente me gustó la pereza de Python 2print quick_debug_varOrwellophile 23 de marzo a las 6:15
28

¿O es como decir "Ya que esto es python v2.7, use esa función diferente de 'imprimir' que también se ha agregado a python v2.7, después de que se agregó en python 3. Entonces mi 'impresión' ya no será declaraciones (por ejemplo, imprimir "mensaje") pero funciones (por ejemplo, imprimir ("mensaje", opciones). De esa manera, cuando mi código se ejecute en Python 3, 'imprimir' no se romperá ".

En

from __future__ import print_function

print_function es el módulo que contiene la nueva implementación de 'print' según su comportamiento en python v3.

Esto tiene más explicación: http://python3porting.com/noconv.html

2

Uno de los usos que encontré muy útil es el módulo print_functionfrom __future__.

En Python 2.7, quería que los caracteres de diferentes declaraciones de impresión se imprimieran en la misma línea sin espacios.

Se puede hacer usando una coma (",") al final, pero también agrega un espacio extra. La declaración anterior cuando se usa como:

from __future__ import print_function
...
print (v_num,end="")
...

Esto imprimirá el valor de v_numde cada iteración en una sola línea sin espacios.

0

__future__es un módulo de Python . Se agregó para evitar confundir las herramientas existentes que analizaban las declaraciones de importación y esperaban encontrar los módulos que están importando. Se agregó en la versión 2.1, por lo que la importación __future__fallará si se usa antes de la versión 2.1.

Ahora mira este código:

>>> from __future__ import division
>>> division
_Feature((2, 2, 0, 'alpha', 2), (3, 0, 0, 'alpha', 0), 131072)

La división regresó con el formato de _Feature(OptionalRelease, MandatoryRelease, CompilerFlag). OptionalRelease y MandatoryRelease son 5 tuplas en forma de:

(
 PY_MAJOR_VERSION, # the 2 in 2.1.0a3; an int
 PY_MINOR_VERSION, # the 1; an int
 PY_MICRO_VERSION, # the 0; an int
 PY_RELEASE_LEVEL, # "alpha", "beta", "candidate" or "final"; string
 PY_RELEASE_SERIAL # the 3; an int
)

Entonces, en nuestro caso, OptionalRelease es 2.2.0a2 y MandatoryRelease es 3.0.0a0.

OptionalRelease nos dice la primera versión en la que se aceptó la función.

MandatoryRelease predice cuándo la característica será parte del idioma o muestra cuándo la característica se convirtió en parte del idioma; en las versiones en o después de eso, los módulos ya no necesitan una declaración futura para usar la función en cuestión, pero pueden continuar usando dichas importaciones. Si MandatoryRelease es None, la función planificada se descarta.

CompilerFlag es el indicador (campo de bits) que debe pasarse en el cuarto argumento a la función incorporada compile () para habilitar la función en el código compilado dinámicamente. Esta bandera se almacena en el atributo compiler_flag en las instancias _Feature.

-4

Después de Python 3.0 en adelante, la impresión ya no es solo una declaración, sino una función. y está incluido en PEP 3105.

También creo que el paquete Python 3.0 todavía tiene estas funciones especiales. Veamos su usabilidad a través de un "programa piramidal" tradicional en Python:

from __future__ import print_function

class Star(object):
    def __init__(self,count):
        self.count = count

    def start(self):
        for i in range(1,self.count):
            for j in range (i): 
                print('*', end='') # PEP 3105: print As a Function 
            print()

a = Star(5)
a.start()

Output:
*
**
***
****

Si usamos la función de impresión normal, no podremos lograr el mismo resultado, ya que print () viene con una nueva línea adicional. Entonces, cada vez que se ejecute el bucle for interno, se imprimirá * en la siguiente línea.