Для чого використовується __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.