Для чого використовується __future__ в Python та як / коли його використовувати та як це працює


694

__future__часто з’являється в модулях Python. Я не розумію , що __future__це і як / коли використовувати його навіть після прочитання пітона __future__дока .

Хтось може пояснити на прикладах?

Кілька відповідей щодо базового використання __future__я отримав правильне.

Однак мені потрібно зрозуміти ще одне, що стосується того, як __future__працює:

Найбільш заплутаною для мене концепцією є те, як поточний реліз python включає функції для майбутніх версій, і як програма, що використовує функцію з майбутнього випуску, може бути успішно складена в поточній версії Python.

Я здогадуюсь, що поточний випуск укомплектований потенційними функціями на майбутнє. Однак функції доступні лише за допомогою, __future__оскільки вони не є чинним стандартом. Дайте мені знати, чи я маю рацію.


10
Це оригінальна пропозиція щодо майбутнього твердження. Мені здалося корисним зрозуміти, чому це в першу чергу, і тому, коли і як це використовувати, слід природно. python.org/dev/peps/pep-0236
Jpaji Rajnish


3
Майбутня заява - це директива для компілятора, що певний модуль повинен бути скомпільований, використовуючи синтаксис або семантику, які будуть доступні у визначеному майбутньому випуску Python. Майбутня заява призначена для полегшення переходу на майбутні версії Python, які вносять несумісні зміни в мову. Це дозволяє використовувати нові функції на основі модулів до випуску, в якому функція стає стандартною.
shivam13juna

Відповіді:


384

З __future__включенням модуля ви можете повільно звикати до несумісних змін або до таких, що вводять нові ключові слова.

Наприклад, для використання контекстних менеджерів вам довелося це зробити from __future__ import with_statementв 2.5, оскільки withключове слово було новим і більше не повинно використовуватися як імена змінних. Для того, щоб використовувати withяк ключове слово Python в Python 2.5 або пізнішої версії, вам потрібно буде використовувати імпорт зверху.

Інший приклад -

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

Без цього __future__матеріалу обидва printтвердження надрукували б 1.

Внутрішня різниця полягає в тому, що без цього імпорту /використовується відображення __div__()методу, тоді як з ним __truediv__()використовується. (У будь-якому випадку, //дзвінки __floordiv__().)

Пропозиція print: printстає функцією в 3.x, втрачаючи своє особливе властивість як ключове слово. Тож навпаки.

>>> print

>>> from __future__ import print_function
>>> print
<built-in function print>
>>>

151
не забувайте from __future__ import braces: p
mdeous

13
@zoogleflatt Якщо ви більше табулятор, ви не знаєте PEP 8. Настійно рекомендується не використовувати вкладки ...
glglgl

5
@glglgl Технічно це просто говорить, що вони віддають перевагу. Після прочитання мені було не зовсім зрозуміло, чому це саме так, я здогадуюсь, що рівні відступів точно збігаються, щоб зробити код більш охайним?
Jpaji Rajnish

4
@zoogleflatt Це, безумовно, також пов'язане з тим, що більшість людей використовують 4 пробіли для 1 рівня відступу, що з міркувань сумісності одна вкладка еквівалентна 8 пробілам, а змішування вкладок і пробілів не рекомендується (відповідно, AFAIK, навіть заборонено в Py3)
glglgl

1
@whiteSkar Наразі я не в курсі новіших версій python 3, але я припускаю, що він все ще використовується, просто що вам, мабуть, це не потрібно з цими досить старими функціями. У Python 3, printбезумовно, є функцією, але можуть бути й інші функції, які можуть використовуватись __future__. (Редагувати: див. Docs.python.org/3/library/__future__.html, де він досі використовується.)
glglgl

195

Коли ви робите

from __future__ import whatever

Ви фактично не використовуєте importзаяву, а майбутню заяву . Ви читаєте неправильні документи, оскільки ви фактично не імпортуєте цей модуль.

Майбутні висловлювання особливі - вони змінюють спосіб розбору вашого модуля Python, тому вони повинні бути вгорі файлу. Вони надають нового - або іншого - значення слів або символів у вашому файлі. З документів:

Майбутня заява - це директива для компілятора, що певний модуль повинен бути скомпільований, використовуючи синтаксис або семантику, які будуть доступні у визначеному майбутньому випуску Python. Майбутня заява призначена для полегшення переходу на майбутні версії Python, які вносять несумісні зміни в мову. Це дозволяє використовувати нові функції на основі модулів до випуску, в якому функція стає стандартною.

Якщо ви дійсно хочете імпортувати __future__модуль, просто зробіть це

import __future__

а потім отримати доступ до нього, як зазвичай.


4
Технічно це також імпорт імпорту, оскільки відповідна назва пов'язана з локальною змінною. from __future__ import print_functionобидва змінюють поведінку printключового слова і впливають на час виконання, еквівалентніprint_function = __import__("__future__").print_function
pppery

112

__future__ це псевдомодуль, який програмісти можуть використовувати для включення нових мовних функцій, несумісних із поточним перекладачем . Наприклад, вираз, який 11/4зараз оцінюється на 2. Якщо модуль, в якому він виконується, увімкнув справжній поділ, виконавши:

from __future__ import division

вираз 11/4буде оцінюватися до 2.75. Імпортуючи __future__модуль та оцінюючи його змінні, ви можете бачити, коли нова мова вперше була додана до мови та коли вона стане за замовчуванням:

  >>> import __future__
  >>> __future__.division
  _Feature((2, 2, 0, 'alpha', 2), (3, 0, 0, 'alpha', 0), 8192)

1
Отже, виходячи з версії випуску змінних, якщо ваш інтерпретатор використовує більш пізню версію, ніж вказати, то import __future__ xyzце неоперативний варіант ?
Рей

4
Це дещо аналогічно поліфункції у світі браузера
cs01

47

Він може бути використаний для використання функцій, які з'являться у нових версіях, маючи старіший випуск Python.

Наприклад

>>> from __future__ import print_function

дозволить вам використовувати printяк функцію:

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

29

Вже є кілька чудових відповідей, але жодна з них не стосується повного списку того, що __future__заява на даний момент підтримується.

Простіше кажучи, заява змушує перекладач Python використовувати нові можливості мови.__future__


Наразі його функції підтримують:

nested_scopes

До Python 2.1 наступний код буде викликати NameError :

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

from __future__ import nested_scopesДиректива дозволить цій функції повинна бути включена.

generators

Введені функції генератора, такі як наведена нижче, для збереження стану між послідовними викликами функцій:

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

division

Класичний поділ використовується у версіях Python 2.x. Це означає, що деякі твердження про поділ повертають розумне наближення поділу ("справжній поділ"), а інші повертають слово ("поділ підлоги"). Починаючи з Python 3.0, справжній поділ визначається символом x/y, тоді як поділ підлоги визначається символом x//y.

У from __future__ import divisionдирективі притискає використання Python 3.0 поділу стилю.

absolute_import

Дозволяє дужкам укладати кілька importоператорів. Наприклад:

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

Замість:

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

Або:

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

with_statement

Додає оператор withяк ключове слово в Python, щоб усунути необхідність у try/finallyоператорах. Найпоширеніші способи використання цього під час виконання вводу-виводу файлів, наприклад:

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

print_function:

Примушує використовувати print()виклик функції в дужках Python 3 замість print MESSAGEоператора стилю.

unicode_literals

Вводить буквальний синтаксис для bytesоб’єкта. Тобто такі твердження, як, bytes('Hello world', 'ascii')можна просто виразити як b'Hello world'.

generator_stop

Замінює використання StopIterationвиключення, що використовується всередині функцій генератора, за RuntimeErrorвинятком.

Ще одне використання, яке не згадувалося вище, полягає в тому, що __future__заява також вимагає використання інтерпретаторів Python 2.1+, оскільки використання старішої версії призведе до виключення з виконання.


Список літератури


Якщо припустити, що ви в автономному режимі, як python знає, чи доступна майбутня версія чи ні? І як він використовує майбутні функції, якщо ви не встановили майбутню версію python на своєму комп’ютері?
Мохсен Хаддаді

25

Або це як сказати "Оскільки це python v2.7, використовуйте таку іншу функцію 'print', яка також була додана до python v2.7, після того, як вона була додана в python 3. Отже, моя" print "більше не буде заявами (наприклад, надрукувати "повідомлення"), але функцій (наприклад, print ("повідомлення", параметри). Таким чином, коли мій код запускається в python 3, "print" не порушиться. "

В

from __future__ import print_function

print_function - це модуль, що містить нову реалізацію 'print' відповідно до того, як він поводиться в python v3.

Це має додаткові пояснення: http://python3porting.com/noconv.html


2

Одне із застосувань, яке я вважаю дуже корисним - це модуль print_functionвід __future__.

У Python 2.7 я хотів, щоб символи з різних заяв про друк друкувалися в одному рядку без пробілів.

Це можна зробити за допомогою коми (",") в кінці, але це також додасть додатковий пробіл. Вищенаведене твердження, коли використовується як:

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

Це надрукує значення v_numкожної ітерації в одному рядку без пробілів.


-4

Після Python 3.0 далі друк вже не є лише твердженням, а функцією. і включено до PEP 3105.

Крім того, я думаю, що у пакета Python 3.0 ще є ці особливі функції. Давайте побачимо його зручність використання завдяки традиційній програмі "Піраміда" в 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:
*
**
***
****

Якщо ми використовуємо звичайну функцію друку, ми не зможемо досягти того ж результату, оскільки print () поставляється з додатковим новим рядком. Отже, кожного разу, коли внутрішній цикл буде виконуватися, він надрукує * на наступний рядок.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.