LINUX.ORG.RU

Ну как бы в лямбдах разрешено изменять значение переменных, так в чем проблема

pylin ★★★★★
()
Ответ на: комментарий от Y

Создать вторую переменную?)

Ну как бы в лямбдах разрешено изменять значение переменных, так в чем проблема

Никак, это переменная цикла и хотелось бы, чтоб подставлялось число, которое в данный момент в перменной.

Glaciuse
() автор топика
>>> a = 5
>>> f1 = lambda a=a: print(a)
>>> a = a + 1
>>> f2 = lambda a=a: print(a)
>>> f1()
5
>>> f2()
6
anonymous
()
Ответ на: комментарий от anonymous

Вся читабельность питона одной строкой

Четко прописан захват именно текущего значения переменной, какие проблемы?

tailgunner ★★★★★
()

В питене примитивные типы по ссылке передаются? Не удивительно что он тормоз такой.

crowbar
()
Ответ на: комментарий от aedeph_

Как же есть

Вот так.

очевидно нет

Ты пытаешься меня обмануть.

будь чёток.

Я настолько чёток, что не нуждаюсь в доказательстве этого.

tailgunner ★★★★★
()
Ответ на: комментарий от anonymous

А чо если лямбда с параметром? А если его щас передать?

А догадайся.

tailgunner ★★★★★
()

Из известных мне языков замыкания передаются по значению только в F#, Haskell, Ocaml, а также иногда в Scala (если val). Даже в лиспах исторически передаются по ссылке. Что тут и говорить про питон?!

dave ★★★★★
()
Ответ на: комментарий от tailgunner

Это не «чётко прописан захват». Это скорее «использован хитрый хак, связанный с тем, что питон по историческим причинам только один раз инициализирует дефолтное значение»

userid2
()
Ответ на: комментарий от userid2

Это не «чётко прописан захват». Это скорее «использован хитрый хак

Этот «хитрый хак» настолько прост, общеизвестен и недвусмысленен, что это именно «четко прописанный захват».

питон по историческим причинам только один раз инициализирует дефолтное значение»

Это базовая семантика языка, а не исторические причины.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Все таки «захват» (в смысле замыкания) у Virtuos86 в Вопрос по python и lambda (комментарий), а с дефолтным значением таки общеизвестный «хак», я бы его назвал «стандартным приемом» или как то так. Половина гуйни в ткинтере так работает;-)

AIv ★★★★★
()
Ответ на: комментарий от AIv

Все таки «захват» (в смысле замыкания) у Virtuos86 в Вопрос по python и lambda (комментарий), а с дефолтным значением таки общеизвестный «хак»

Это еще один способ (не более и не менее хак, чем с дефолтным значением), но шашлыки лямбд - не мое любимое блюдо %) Когда первый раз увидел такой код - с минуту пытался его интерпретировать.

Половина гуйни в ткинтере так работает;-)

Ради интереса грепнул lib-tk: всего-то 5 лямбд, из них 2 - с дефолтными аргументами, вложенных нет.

tailgunner ★★★★★
()
Ответ на: комментарий от AIv

А что не так с «захватом в смысле замыкания»? Захватывается ссылка на память, где лежит значение переменной. Если понимать = как деструктивный модификатор, то всё верно: изменяется-то значение в памяти. Те же Лиспы все такие.

А вот в ML-семействе присваивание понимается как создание нового места в памяти под значение и пересвязывание имени переменной с этим местом. Поэтому там замыкания всегда сохраняют текущее значение.

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

ilammy ★★★
()
Ответ на: комментарий от tailgunner

но шашлыки лямбд - не мое любимое блюдо %)

Там дело не в лямбдах, это стандартное замыкание записанное в одну строку. Ты не любишь декораторы «и вот это вот все»?;-)

Ради интереса грепнул lib-tk: всего-то 5 лямбд, из них 2 - с дефолтными аргументами, вложенных нет.

Я про использование. Когда хочется повесить коллбэк в который надо просунуть каких то текущих значений параметров, дефолтные значения лямбд самое то. Иначе вместо длинных однострочников получается адЪ и израиль (каша из многа букв).

AIv ★★★★★
()
Ответ на: комментарий от ilammy

А что не так с «захватом в смысле замыкания»?

Все так. Но обычно это юзают в более сложных случаях чем у ТС;-)

Если понимать = как деструктивный модификатор

«Неприличным словами не выражаться!»(ц)

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

Можно и так на это смотреть. Но между нами девочками - у ТС явный косяк с дизайном, раз в такой задаче дошло до подобных извращений.

AIv ★★★★★
()
Ответ на: комментарий от tailgunner

tailgunner ★★★★★

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

Вся читабельность питона одной строкой

aedeph_ ★★
()
Ответ на: комментарий от AIv

но шашлыки лямбд - не мое любимое блюдо %)

Там дело не в лямбдах

А в чем? Внешняя лямбда создает область видимости с одной переменной (внутри которой переменная не меняется) внутренняя использует эту область видимости. Создать область видимости без def можно только лямбдой.

Ты не любишь декораторы «и вот это вот все»?;-)

Декораторы - это синтаксический сахар, а две лямбды + вызов только что созданного объекта - это слишком хардкорно на мой взгляд. Хорошо для учебного примера, но преимуществ перед дефолтными аргументами я не вижу.

tailgunner ★★★★★
()
Ответ на: комментарий от aedeph_

О чем ты? Меня озадачил код из вложенных лямбд, про «всю читабельность» анонимус ответил мне, но я-то вложенных лямбд не писал.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Создать область видимости без def можно только лямбдой.

exec/eval? Можно еще модуль сделать;-)

преимуществ перед дефолтными аргументами я не вижу.

Если невозможен вызов функции с какими то левыми аргументами которые перекроют дефолтные, то их и нету. Так я и не говорю что они есть, я просто к терминологии придрался;-)

AIv ★★★★★
()
Ответ на: комментарий от tailgunner

My fault, не заметил варианта из вложенных лямбд. Который кстати, читаемее и идиоматичнее опциональных аргументов. По крайней мере ведёт себя правильнее: упадёт на f1(777).

aedeph_ ★★
()
Ответ на: комментарий от ilammy

там явно создаётся новая переменная a лично для замыкния.

Вот объяснение что происходит: http://me.veekun.com/blog/2011/04/24/gotcha-python-scoping-closures/

Что касается «создаётся новая переменная», то я бы не стал так говорить, в питоне ты владеешь только референсами. Плюс есть свои нюансы при работе с иммутабельными типами.

true_admin ★★★★★
()
Ответ на: комментарий от true_admin

Не новая переменная, не референс, а cell object.

Нюансов по иммутабельности никаких нет, поведение прямолинейное.

aedeph_ ★★
()
Ответ на: комментарий от true_admin

Костыль из-за непроразчного скоупинга прекрасно спроектированного языка программирования python. Сначала создаётся не a, а новый локальный контекст, связь с которым и необходимо запомнить для функциональных объектов.

Функциональный объект сохраняет в tuple'е __closure__ cell objects, как обёртки над референсами.

aedeph_ ★★
()
Ответ на: комментарий от aedeph_

Сначала создаётся не a, а новый локальный контекст, связь с которым и необходимо запомнить для функциональных объектов.

Я так ничего не понял :(. Это же просто прокси, зачем оно нужно? Я посмотрел ./Objects/cellobject.c, там тупо обёртка без каких-либо примочек.

У меня только одно объяснение — оно нужно чтобы чисто держать референс на проксируемый объект. Но почему нельзя обойтись без него я не понимаю.

true_admin ★★★★★
()
Ответ на: комментарий от aedeph_

Переформулирую вопрос: почему в локальном контексте нельзя сразу пихать референсы на внешние переменные.

true_admin ★★★★★
()
Ответ на: комментарий от aedeph_

После «уничтожения» (выхода из) внешнего контекста на что ссылаться?

Объекты уничтожаются не когда контекст уничтожается, а когда reference count становится нулём. Чем плохо удерживать референс в том же самом __closure__?

true_admin ★★★★★
()
Ответ на: комментарий от aedeph_

Объекты будут уничтожены когда у них ref_cnt уйдёт в ноль. Когда ты что-то засовываешь в тьюпл то ref_cnt инкрементируется, поэтому уничтожение фрейма внешней функции ничего не уничтожет.

true_admin ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.