Комментарии 39
спасибо. ждем вторую часть
Что в декораторах такого волшебного и непостижимого, заставляющего писать очередной пост про них?
Для людей, давно и серьёзно занимающихся программированием — почти ничего.
Для новичков, как показывает практика, эта тема неочевидна.
Плюс, во второй части будет больше неочевидных вещей, таких как: фабрики декораторов, декораторы с параметрами, декораторы для методов и т.д.
Надеюсь, наличие данного материала на русском никому не повредит:)
Для новичков, как показывает практика, эта тема неочевидна.
Плюс, во второй части будет больше неочевидных вещей, таких как: фабрики декораторов, декораторы с параметрами, декораторы для методов и т.д.
Надеюсь, наличие данного материала на русском никому не повредит:)
Я больше скажу. Некоторым еще и полезна будет.
Напишите, если не трудно про y-комбинатор, а то статья на хабре просто мне мозг выломала( хотя там строчек кода штук 5 на пример). Так полностью и не понял.
НЛО прилетело и опубликовало эту надпись здесь
Y-комбинатор позволяет в анонимной функции использовать рекурсию с использованием самой себя, без необходимости назначения ей имени — функция остаётся анонимной.
Скажем, у нас есть неанонимная рекурсивная функция вычисления факториала:
Это работает, т.к. у нашей функции есть имя fact и мы можем по нему функцию вызывать внутри неё самой.
Но если мы захотим написать анонимную функцию вычисления факториала, мы столкнемся с проблемой — как нам внутри функции вызвать её саму, не имея имени.
Можно попробовать сделать так:
В данном случае имя функции не встречается внутри неё. Но при внешнем вызове функции приходится передавать в качестве одного из аргументов ссылку на неё саму. Это можно обернуть так:
Теперь мы её ещё немного дообернем:
Вот y и есть Y-комбинатор, к тому же анонимный. Пользуем inline как то так:
PROFIT! :)
Скажем, у нас есть неанонимная рекурсивная функция вычисления факториала:
def fact(n):
return n * fact(n-1) if n > 0 else 1
print fact(10)
Это работает, т.к. у нашей функции есть имя fact и мы можем по нему функцию вызывать внутри неё самой.
Но если мы захотим написать анонимную функцию вычисления факториала, мы столкнемся с проблемой — как нам внутри функции вызвать её саму, не имея имени.
Можно попробовать сделать так:
fact = lambda self, n: n * self(self, n) if n > 0 else 1
print fact(fact, 10)
В данном случае имя функции не встречается внутри неё. Но при внешнем вызове функции приходится передавать в качестве одного из аргументов ссылку на неё саму. Это можно обернуть так:
wrap = lambda fn, *args: fn(fn, *args)
fact = lambda self, n: n * self(self, n) if n > 0 else 1
print wrap(fact, 10)
Теперь мы её ещё немного дообернем:
y = lambda fn: lambda *args: fn(fn, *args)
fact = y(lambda self, n: n * self(self, n) if n > 0 else 1)
Вот y и есть Y-комбинатор, к тому же анонимный. Пользуем inline как то так:
# применяем анонимную рекурсивную функцию
map(
(lambda fn: lambda *args: fn(fn, *args))(
lambda self, n: n * self(self, n-1) if n > 0 else 1),
[1,2,3]
)
PROFIT! :)
Видимо тем, что остальные статьи заканчивались на первом примере этого поста.
Иными словами автор выбрал несколько иной подход, сперва привел итоговый пример, а затем разложил все по полочкам, так сказать сохранил интригу и не дал заснуть.
Иными словами автор выбрал несколько иной подход, сперва привел итоговый пример, а затем разложил все по полочкам, так сказать сохранил интригу и не дал заснуть.
Что в декораторах такого волшебного и непостижимого, заставляющего писать очередной пост про них?Для человека, издревле работающего с питоно-подобными языками ничего.
А вот программера, взрощенного на светлых идеалах паскале- и си-подобных языков, поначалу несколько обескураживает фраза «каждая функция есть объект». А последующее знакомство с теми же декораторами вообще вводит в некоторое замешательство, требующее осознания и последующей перестройки некоторых принципов, укрепившихся в мозге. Вот тут-то подобные статьи и оказываются очень кстати.
Ведь чем более разнообразным количеством слов и статей будет описана некая сущность, тем проще её разложить по полочкам и осознать.
На Си всё не так плохо, если не требуется метапрограммирование и прочий манкипатчинг. Указатели на функцию в данном контексте являются практическим полным аналогом ссылки на объект Function — можно присваивать переменным, можно вызывать из переменной, можно передавать в другие функции, а значит можно использовать паттерн «декоратор».
хаскель-барби смотрит на питоновцев и точно также (только с большими глазами) недоумевает — чего такого волшебного в монадах, что о них пишет какждый, освоивший хаскель и умеющий писать.
В статье не упоминается что декораторы могут быть применены не только к функциям, но и к целым классам! Таким образом они могут управлять вызовами классаов с целью создания экземпляров, и самими объектами классов, например добавлять новые методы в классы.
так же нет инфы что декораторы могут вызываться с аргументами
Если бы вы посмотрели по ссылке на оригинал, то заметили бы, что после данного материала идёт как раз «Passing arguments to the decorated function» («Передаем аргументы декорируемым функциям») и «Decorating methods» («Декорируем методы»). Вызов декораторов с параметрами так-же будет во второй части, как я успел упомянуть в этом комментарии.
Резюмируя: не спешите, всё будет:)
И спасибо за критику!
Резюмируя: не спешите, всё будет:)
И спасибо за критику!
habrahabr.ru/post/74838/
habrahabr.ru/post/46306/
habrahabr.ru/post/86255/
habrahabr.ru/post/139866/
Вот ей богу не надоело еще ??? Мне даже кармы не жалко — но… прям ррр… Я сам php разработчик, начал недавно изучать python. Так вот в питоне куча всего интересного, помимо декораторов. И ими начинающие вряд ли со старта пользоваться будут, а если будут то еще быстрее запутаются (особенно полезен совет вложить декоратор в декоратор — вордпрес напоминает 2 версии, там не декораторы но пол движка на хуках...).
Одновременное использование нескольких версий на одной машине (linux), параллельные вычисление, отладка кода, оптимизация, подсчет занимаемой памяти и куча всего всего — довольно ж сильный язык жеж? Что мусолить одну тему по 10 раз?
habrahabr.ru/post/46306/
habrahabr.ru/post/86255/
habrahabr.ru/post/139866/
Вот ей богу не надоело еще ??? Мне даже кармы не жалко — но… прям ррр… Я сам php разработчик, начал недавно изучать python. Так вот в питоне куча всего интересного, помимо декораторов. И ими начинающие вряд ли со старта пользоваться будут, а если будут то еще быстрее запутаются (особенно полезен совет вложить декоратор в декоратор — вордпрес напоминает 2 версии, там не декораторы но пол движка на хуках...).
Одновременное использование нескольких версий на одной машине (linux), параллельные вычисление, отладка кода, оптимизация, подсчет занимаемой памяти и куча всего всего — довольно ж сильный язык жеж? Что мусолить одну тему по 10 раз?
Спасибо за комментарий!
Попробую ответить на всё.
1. На Хабре ≈140000 статей, не удивительно, что есть статьи по схожим темам. Уверяю вас, перед тем, как браться за перевод я поискал материалы по данной теме на Хабре и, по моему мнению, тот, что перевожу я, не является дублирующим в целом.
2. Со старта — не будут. Но когда-нибудь ведь начнут:)
3. В данной статье нету советов, лишь описание того, как это работает.
4. Надеюсь, вторая часть Вам покажется более «незамусоленой».
Попробую ответить на всё.
habrahabr.ru/post/74838/
habrahabr.ru/post/46306/
habrahabr.ru/post/86255/
habrahabr.ru/post/139866/
1. На Хабре ≈140000 статей, не удивительно, что есть статьи по схожим темам. Уверяю вас, перед тем, как браться за перевод я поискал материалы по данной теме на Хабре и, по моему мнению, тот, что перевожу я, не является дублирующим в целом.
ими начинающие вряд ли со старта пользоваться будут, а если будут то еще быстрее запутаются
2. Со старта — не будут. Но когда-нибудь ведь начнут:)
особенно полезен совет вложить декоратор в декоратор
3. В данной статье нету советов, лишь описание того, как это работает.
Что мусолить одну тему по 10 раз?
4. Надеюсь, вторая часть Вам покажется более «незамусоленой».
Отличная статья, спасибо! Просто и понятно.
У меня есть вопрос, возможно глупый, но все же:
зачем разработчики python сделали что функция-декоратор возвращает функцию-обёртку, которая затем вызывается? Как мне это можно было сделать следующим образом: когда вызывается декорированная функция, вместо нее просто вызывается функция-декоратор, который получает первым аргументом данную функцию.
Демонстрация кодом:
def decorator ():
…
@ decorator
def func ():
…
Сейчас сделано так:
decorator (func) ()
Мой вариант:
decorator (func)
Я не говорю что мой вариант лучше.
зачем разработчики python сделали что функция-декоратор возвращает функцию-обёртку, которая затем вызывается? Как мне это можно было сделать следующим образом: когда вызывается декорированная функция, вместо нее просто вызывается функция-декоратор, который получает первым аргументом данную функцию.
Демонстрация кодом:
def decorator ():
…
@ decorator
def func ():
…
Сейчас сделано так:
decorator (func) ()
Мой вариант:
decorator (func)
Я не говорю что мой вариант лучше.
Потому что func без скобок возвращает объект Function. Если мы декорируем его, то тип возврата не должен изменяться, декорация должна быть прозрачной для вызывающего кода. Везде где используется func, должна использоваться и decorator(func). Например, вложенные декораторы — как вы в своем варианте их реализуете?
Ваш вариант сработает для декораторов простейших функций.
Но, предположим, Вам нужно декорировать такую ф-ию:
Тогда, вызвав
В случае
Надеюсь, я верно понял суть Вашего вопроса?:)
Но, предположим, Вам нужно декорировать такую ф-ию:
def func(var):
print "I've got", var
Тогда, вызвав
decorator(func)("10$")
мы получим ожидаемое поведение.В случае
decorator(func)
нам просто «некуда» передать аргумент (как пробрасывать аргументы через декоратор — в скором времени будет показано).Надеюсь, я верно понял суть Вашего вопроса?:)
# Возьмём функцию и запишем её в переменную
talk = getTalk()
Скобки же не нужны?
что-за редактор, шрифт, тема на скрине?
Теперь мы знаем, что функции являются полноправными объектами
Из ваших примеров этого не следует. В своих примерах вы лишь показываете, что в питоне есть функции высшего порядка. Они, например, есть и в php, но, тем не менее, в php функция не является объектами.
А еще там есть отличные ответы этого же человека про итераторы и метаклассы. Непонятно только, зачем все это переводить в бесконечном количестве. Все подобные хорошие посты в первых 2-3 ссылках по запросам в поисковике.
«вы можете назначить её переменнной», «помещаем в переменную», «записаны в переменную»
Есть хороший термин «связать с перменной», без риска свалиться в вопросы — где располагается то место в которое что-то помещается, сколько места занимает ссылка на объект, итп.
Есть хороший термин «связать с перменной», без риска свалиться в вопросы — где располагается то место в которое что-то помещается, сколько места занимает ссылка на объект, итп.
«раз мы можем возвращать функцию, значит, мы можем и передавать её другой функции, как параметр»
Это два разных явления, являющимися следствиями того, что функции являются объектами «первого класса».
Это два разных явления, являющимися следствиями того, что функции являются объектами «первого класса».
НЛО прилетело и опубликовало эту надпись здесь
великолепный пример с седвичем.
Просто отличная оригинальная статья и замечательный ее перевод! Спасибо огромное. Самый приятный, нескучный и понятный стиль объяснения.
Спасибо огромное самое вменяемое объяснение.
А как завернуть декоратор, начинающийся с собаки @ в if ?
На сколько я понимамю, декоратор работает только без отступов от начала строки.
Спасибо автору за статью и за то, что она оказалась не такой длинной, как он обещал)
После того, как начались длинные названия функций, я перестал читать. Я, и так, больше люблю смотреть и слушать, а тут куча слов, да еще и на английском....
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Понимаем декораторы в Python'e, шаг за шагом. Шаг 1