Expert JS React Developers for TUI wanted. Join Ciklum and get a $4000 sign-on bonus!
×Закрыть

Вышла первая альфа Python 3.0

Итак, свершилось. В доказательство тому, что Python 3 не превратится в безнадежный долгострой на манер Perl 6 вышла первая альфа. Вместо разработки новой версии с нуля (и как следствие неизбежного попадания в ловушку «эффекта второй системы»), было решено прежде всего очистить язык от накопившихся за долгие годы разнообразных компромисов, обусловленных необходимостью нести бремя обратной совместимости, и ограничиться относительно небольшим колличеством нововеденний.

Рассмотрим основные изменения.

Строки

  • Полностью переделана работа со строками. Теперь есть два типа данных — строки (str) и байты (bytes). Строки подобны типу данных unicode из Python 2.x (т.е. все строки теперь юникодные!). Байты хранят двоичные данные (текст в какой-либо кодировке, который обрабатывается как двоичные данные, пока вы не решите декодировать его). Строки и байты нельзя смешивать, вы всегда должны явно преобразовывать их, используя методы .encode() (str -> bytes) или .decode() (bytes -> str).
  • Вместо оператора % у строк появился метод format:
    "The story of {0}, {1}, and {c}".format(a, b, c=d)
    Каждый аргуммент функции format получает порядковый номер начиная с нуля, так в данном примере — ’a’ это аргумент 0, ’b’ - агрумент 1. Именные аргументы идентифицируются по имени. Функция включает в себя возможности выравнивания текста, работу с различными типами данных и проч.Несколько примеров использования:
    "My name is {<a href="http://0.name" target="_blank">0.name</a>}".format(file('out.txt'))
    "My name is {0[name]}".format(dict(name='Fred'))"
    "Today is: {0:a b d H:M:S Y}".format(datetime.now())
    Предствлен класс Formatter, который позволяет легко создавать свои версии функции format. Например, можно сделать вариант format, котрый получает доступ непсоредственно к переменным из заданной области видимости:
    fmt = NamespaceFormatter(globals()) greeting = "hello" print(fmt("{greeting}, world!"))
  • Кодировка исходного кода по-умолчанию теперь UTF-8.
  • Модули StringIO и cStringIO удалены. Вместо них следуют использовать StringIO или BytesIO из модуля io.

Исключения

  • Исключения должны наследоваться от BaseException. StandardException удален.
  • Вместо except E, e: теперь следует использовать except E as e:, а вместо raise Exception, args — raise Exception(args)

Классы

  • Наконец-то в языке остался лишь один вид классов. «Классические» классы удалены.
  • Новый синтаксис для метаклассов. Теперь метакласс указывается через аргумент в списке базовых классов: class Foo(base1, base2, metaclass=mymeta): вместо прежнего указания в теле класса __metaclass__ = mymeta
  • Появились декораторы для классов.

Различные изменения

  • Добавлены аннотации функций.
  • Новые возможности распаковки последовательностей. Теперь можно делать так: a, b, *rest = some_sequence и даже так *rest, a = stuff. rest всегда список; правая часть выражения обязательно должна быть итерабельна.
  • При делении целых теперь получается вещественное число. Для получения целого используйте 3//2.
  • Удален оператор <>. Используйте вместо него !=.
  • long переименован в int. Теперь есть только один встроеный тип для целых — int.
  • Добавлено ключевое слово nonlocal для доступа к пременным во внешней (не глобальной) области видимости. (Привет полноценные замыкания? ;) )
  • print теперь функциия, а не ключевое слово.
  • Функция xrange() переименована в range().
  • Функции zip(), map() и filter() возвращают итераторы.
  • Удалены следующие функции: apply(), callable(), coerce(), execfile(), file(), reduce(), reload().
  • Удален метод dict.has_key() (используйте вместо него k in dict)

Ссылки:

Список изменений

Утилита для упрощения перевода кода со второй версии на третью

👍НравитсяПонравилось0
В избранноеВ избранном0
Подписаться на автора
LinkedIn

Похожие статьи




Підписуйтесь: Soundcloud | Google Podcast | YouTube


25 комментариев

Подписаться на комментарииОтписаться от комментариев Комментарии могут оставлять только пользователи с подтвержденными аккаунтами.

В методе timeit по умолчанию 1000000 отераций:)

да, это действительно так. ахаха, как это смешно)) 0ноль)

> измерение всего одной итерации всегда будет давать разный результат.В методе timeit по умолчанию 1000000 отераций:)

это не тот же самый код. простая замена x, y на *args, kwargs сразу же даёт проседание производительности по timeit () на 25%, что в принципе доказывает бредовость идеи меряния количества инструкций и делания на основе этого каких-то выводов — простое изменение кода может убрать всю выигранную производительность. потому что это язык высокого уровня.по поводу фактической производительности. измерение всего одной итерации всегда будет давать разный результат.

print(timeit.Timer("f2(1, 2)", "from main import f2").timeit(1000000))print(timeit.Timer("f1(1, 2)", "from main import f1").timeit(1000000))

3.908798933032.2824139595быстрее не в 4 и не в 2 раза. плюс с использованием *args, kwargs, timeit () при разных замерах даёт отношение первого времени ко второму с вариациями ±10%, что говорит или о том, что timeit () не точен, или о том же, о чём я на писал в первом абзаце.но в целом убедили, да. если дизассемблировать код и считать инструкции, то можно написать быстрее.

Те-же данные для той-же машины и python 2.5.1t_closure = 0.7415t_class = 1.383t_empty = 0.285 (1.383 — 0.285) / (0.7415 — 0.285) = 2.4

Я уже почти устал.> «питоновские инструкции» — это бред. хотите считать инструкции — пишите на ассемблере. питон — это язык высокого > уровня, хотите мерять производительность...Подавляющее большинство низкоуровневых питоновских инструкций исполняются за примерно одинаковое время (а менно такие как add, getattr, getitem, mul,..., усли конечно соотв. операторы не перегружены python/C кодомна что-нить нетривиальное) Мерять такой код профайлером — мягко говоря неправильно т.к. накладные расходы профайлера ЗНАЧИТЕЛЬНО превышают время исполнения кода (что мы тут и видим). Для таких случаев давно уже есть timeit (о чем я, кстати, писал) WinXP SP2, AthlonX2 3600@2.9GhzPython 3.0a1 (py3k: 57844, Aug 31 2007, 16: 54: 27) [MSC v. 1310 32 bit (Intel)] on win32

>>> def closure(func):counter = 1def cl(x):nonlocal countercounter += 1return func(counter,x)return cl>>> class ccl:def init(self,func):self.func = funcself.counter = 1def call(self,val):self.counter += 1return self.func(self.counter,val)>>> @closuredef f1(x,y):pass #мы вроде не сложение меряем а замыкания>>> @ccldef f2(x,y):pass>>> def >>> f1(1)>>> import timeit>>> timeit.Timer("f1(1)","from main import f1").timeit()0.70828024232130105>>> timeit.Timer("f2(1)","from main import f2").timeit()1.8935336753693548>>> def f3(x,y):pass>>> timeit.Timer("f3(1,1)","from main import f3").timeit()0.31531297972230732Накладные расходы замыкания 0.708 - 0.315 = 0.392Накладные расходы класса 1.894 - 0.315 = 1.579С классом в 4(ЧЕТЫРЕ) раз медленнее.

http://www.python.org/dev/peps.../ раздел Rationale, если и после этого будет “не ясно” можно написать в python-dev-request@python.org что замыкания не нужны а nonlocal так вообще нафик.

спасибо, что продолжаете нести бремя додумывания. у вас это хорошо получается.в PEP’е, к счастью, приведён более вменяемый пример, теперь вроде бы понятно зачем нужен nonlocal. только в том примере работа с переменной не в глобальной, и не в локальной области видимости. можно ли считать эо замыканием — не знаю. технически, наверное да. но тогда можно глобальную область видимости назвать «такое большое замыкание». но это не важно, спасибо за разъяснения.

Для 2.X скорость отличается не сильно в данном случае т.к. здесь присутствует оператор [], который трансформируется в три питоновские инструкции. Для 3.0 в этом месте нет дополнительных инструкций. Вариант через классы при каждом обращении к атрибуту требуютдвух дополнительных инструкций. Если бы счетчик не требовался то через замыкания было-бы быстрее и в 2.X.

сначала не хотел на это отвечать, потому что мерять «питоновские инструкции» — это бред. хотите считать инструкции — пишите на ассемблере. питон — это язык высокого уровня, хотите мерять производительность — берите хотя бы профайлер. сто раз это уже обмусоливалось, производительность программы зависит от алгоритмов, а не от 2 лишних инструкций.всё-таки запустил профайлер на python3.код f_dec стал выглядеть так:

def f_dec(func):non_local = 0def dec(*args, kwargs):nonlocal non_localnon_local += 1return func(*args, kwargs)return dec
ncalls tottime percall cumtime percall filename:lineno(function) 1 0.000 0.000 0.000 0.000 :0(__build_class__) 2/1 0.000 0.000 97.174 97.174 :0(exec) 1 0.004 0.004 0.004 0.004 :0(setprofile) 2/1 26.746 13.373 97.174 97.174 :1() 1 0.000 0.000 0.000 0.000 :1(f_dec) 1 0.000 0.000 0.000 0.000 :10(init) 1000000 24.558 0.000 35.290 0.000 :13(call) 1000000 11.193 0.000 11.193 0.000 :18(test1) 1000000 10.733 0.000 10.733 0.000 :22(test2) 1000000 23.946 0.000 35.138 0.000 :3(dec) 1 0.000 0.000 0.000 0.000 :9(c_dec) 1 0.000 0.000 97.178 97.178 profile:0(exec('.. 0 0.000 0.000 profile:0(profiler)

ерунда. ч.т.д.

> Интересно? будет ли полноценная поддержка многомерных массивов? Нет. Если очень нужно используйте numpy — там есть тип для массивов с произвольными Python объектами.http://www.python.org/dev/peps.../

Интересно? будет ли полноценная поддержка многомерных массивов?

Интересно?, eltn kb gjkyjwtyyfz gjllth; rf vyjujvthys [vfccbdjd&

> поэтому зачем нужны такие телодвижения не ясноhttp://www.python.org/dev/peps.../ раздел Rationale, если и после этого будет "не ясно"можно написать в python-dev-request@python.org что замыкания не нужны, а nonlocal так вообще нафик.> почему-то получается не в два раза быстее, а как-то... одинаково.Для 2.X скорость отличается не сильно в данном случае т.к. здесь присутствует оператор [], который трансформируется в три питоновские инструкции. Для 3.0 в этом месте нет дополнительныхинструкций. Вариант через классы при каждом обращении к атрибуту требуютдвух дополнительных инструкций. Если бы счетчик не требовался то через замыкания было-бы быстрееи в 2.X.

Я уже привел пример в 10 м посте.

как раз это мне и не понятно. в 10 посте описан цикл for спрятанный в функцию и выполняющийся через вызов map (). обычный цикл for не имеет проблем с доступом к локальным переменным функции в которой он выполняется, поэтому зачем нужны такие телодвижения не ясно.

import timeit и вперед, или читаем основы оптимизации питоновского кода

спасибо за ссылку. там написаны очень интересные вещи, но можно поступить несколько по-другому — не читать про низкоуровневую оптимизацию в языке высокого уровня, а взять профайлер и посмотреть.def f_dec (func): non_local = [0] def dec (*args, **kwargs): non_local [0] += 1return func (*args, **kwargs) return decclass c_dec: def __init__ (self, func): self.non_local = 0self.func = funcdef __call__ (self, *args, **kwargs): self.non_local += 1return self.func (*args, **kwargs) @f_decdef test1 (x, y): return x + y@c_decdef test2 (x, y): return x + yfor x in xrange (1000000): test1 (1, 2) test2 (1, 2) ncalls tottime percall cumtime percall filename: lineno (function) 1 0.000 0.000 61.856 61.856: 0 (execfile) 1 0.000 0.000 0.000 0.000: 0 (setprofile) 1 0.000 0.000 61.856 61.856: 1 () 1 17.937 17.937 61.856 61.856 perf.py: 1 () 1 0.000 0.000 0.000 0.000 perf.py: 1 (f_dec) 1000000 15.133 0.000 21.621 0.000 perf.py: 12 (__call__) 1000000 6.528 0.000 6.528 0.000 perf.py: 16 (test1) 1000000 6.488 0.000 6.488 0.000 perf.py: 20 (test2) 1000000 15.769 0.000 22.297 0.000 perf.py: 3 (dec) 1 0.000 0.000 0.000 0.000 perf.py: 8 (c_dec) 1 0.000 0.000 0.000 0.000 perf.py: 9 (__init__) 1 0.000 0.000 61.856 61.856 profile: 0 (execfile (’perf.py’)) 0 0.000 0.000 profile: 0 (profiler) почему-то получается не в два раза быстее, а как-то... одинаково.

> Насчет callable: как я понял, предлагается «просто выполнить попытку вызова».Особенно все странно если учесть что при попытке вызова объекта без метода call генеритсяTypeError, а не какое-то специфическое исключение, т.е. в catch придется еще разбиратьсягде исключение было сгенерированно — при попытке вызова или уже при исполнении функции.В общем причин убирания callable я так и не догнал, хотя это довольно долго мусолили в pydev рассылке.

Насчет callable: как я понял, предлагается «просто выполнить попытку вызова». Если нужно обработать ошибку, придется ставить try/catch. По-моему тупо. Я лучше определю свою callable () для Py3k и выше.

> зачем одно выражать через другое я не знаю??? собственно это вы начали рассказывать что вместо замыканий можно классы использовать> может быть nonlocal имеет какое-то другое применение кроме «полноценных замыканий»? Я уже привел пример в 10 м посте.>, а можно озвучить расчёты?...> потому что я не вижу большой разницы между вызовом метода класса с > обращением к члену класса и вызовом функции и обращением к переменной.import timeit и вперед, или читаем основы оптимизации питоновского кода


В таком случае следующим вашим советом должно быть предложение вообще убрать замыкания?

спасибо, что додумываете за меня. мне так гораздо легче.

def f(x):m = 1def inner_f(y): nonlocal inner_z, mm += 1return inner_z(y)def inner_z(y):nonlocal inner_f, mprint(inner_f)return y * x + mreturn inner_f

теже же классы, что и раньше, только писанины добавилось.я к тому, что я не вижу разницы между эмуляцией молотка микроскопом и эмуляцией микроскопа молотком (хотя, конечно, каждый пользуется тем, чем хочет). замыкания — удобный инструмент, классы — тоже удобный инструмент. зачем одно выражать через другое я не знаю и вообще-то об этом и спрашивал. может быть nonlocal имеет какое-то другое применение кроме «полноценных замыканий»?

Кто чем хочет, тот тем и пользуется, к тому-же вариант с замыканиями будет прим.раза в 2 быстрее.

а можно озвучить расчёты? потому что я не вижу большой разницы между вызовом метода класса с обращением к члену класса и вызовом функции и обращением к переменной.

Можно еще так использовать. Тут с классами придется побольше кода написать.

скорее всего классы вообще не придётся писать. это цикл спрятанный в функцию.

> это классы-то «неудобный способ»?, а что тогда удобный? Сразу не понял к чему это было.Раньше это через замыкания делалось примерно так:

def func(m): closure_var = [m] def closure(z): closure_var[0] += 1 return chtoto_tam(z) return closure

В таком случае следующим вашим советом должно быть предложение вообще убрать замыкания? Кто чем хочет, тот тем и пользуется, к тому-же вариант с замыканиями будет прим.раза в 2 быстрее. Можно еще так использовать. Тут с классами придется побольше кода написать.

def r(dt):m = 1def g(x):nonlocal mm += len(x)return chot_tam_delat(x) map(g,dt)return m

это классы-то “неудобный способ”?, а что тогда удобный? class count_calls: def init (self, func): self.counter = 0self.func = funcdef call (self, *args, kwargs): self.counter += 1return self.func (*args, kwargs) @count_callsdef test (x, y): print x + yраньше замыкания классами эмулировали, теперь классы замыканиями?

> что-то я сомневаюсь, что этот код имеет какой-то смысл. потому что значение возвращаемое функцией теперь зависит > не только от параметров фунции, а ещё и от порядка вызова функций.>...> в ленивыом языкеДа, вы не ошиблись, это статья про питон, а не про хаскел)).А нужно это для организации внутренних атомарных переменных в замыкании, которые сохраняют значения между вызовами (это можно было и раньше сделать, но неудобным способом).

def count_calls(func):x = 0def closure(*dt,mp):nonlocal xx += 1return func(x - 1,*dt,mp)return closure@count_callsdef test(x,y): print(x,y)

Конечно. Классический пример замыкания на схеме:

что-то я сомневаюсь, что этот код имеет какой-то смысл. потому что значение возвращаемое функцией теперь зависит не только от параметров фунции, а ещё и от порядка вызова функций.

fx = closure(x)fx(y1)fx(y2)fx(y3)

и

fx = closure(x)fx(y1)fx(y3)fx(y2)

дадут разные результаты. ещё интереснее, если мы замыкания подставим в вызовы функции: another_func (fx (1), fx (2)) в ленивыом языке, т.е. параметры будут вычислены не в момент вызова, а где-то внутри тела функции. изменение такого кода на выходе даст что-то вроде генератора случайных чисел.вобщем интересная идея с замыканием, но нельзя ли увидеть use case?

>> Ага, как если бы она когда-то толком в питоне была.> Ага, как если бы она когда-то толком в питоне была.Очень странное заявление. Совместимость всегда была одним из ключевых факторов при выходе новых версий питона.Собственно вместо удаления какой-либо особенности она просто начинала генерить warning, но продолжала работатьдальше. За все время существования питона несовместимые изменения можно на пальцах пересчитать. (для интереса загляните какое число всего в 2.5 питоне отмечено как depricated, но при этом работает и поддерживается).

> обусловленных необходимостью нести бремя обратной совместимостиАга, как если бы она когда-то толком в питоне была.Совершенно жуткое явление, когда что-либо становится популярным, при этом активно не желая становиться really deployable и тем более maintainable — в этом плане питон по воле Гуидо до сих пор лишь чуточку лучше php: (

Итак, свершилось. В доказательство тому, что Python 3 не превратится в безнадежный долгострой на манер Perl 6 вышла первая альфа.На счет времени появления Perl 6, я как Перловщик не сильно беспокоюсь. Дело в том, что Perl 6 будет новым языком программирования, который абсолютно обратно не совместим с Perl 5. Perl 6, по моему мнению, это не продолжение Perl 5, а попытка создать новый ОО-язык программирования, взявший за основу лишь базовые концепции от Perl 5. Что касаться Питона, так каждая его новая версия — не совместима полностью с исходниками, написанными под предыдущею версию. С одной стороны — это попытка исправить «исторические» ошибки языка, с другой стороны такой подход несет очень большие неудобства для больших проектов.

Первый раз здесь увидел про отмену callable (), и это пожалуй единственное, что не понравилось в изменениях. hasattr (obj, ’call’) уж слишком волосато выглядит.

(Привет полноценные замыкания?;))

а что такое полноценное замыкание? python 2.5:

def f(x):def inner_f(y):return x*yreturn inner_ff10 = f(10)print f10(3)

полноценное замыкание без nonlocal., но если внутри функции сделать x += 1, например, то «local variable ’x’ referenced before assignment», что исправляется nonlocal в python3., но если изменять «замкнутое» значение, то разве это замыкание?

Подписаться на комментарии