Answer the question
In order to leave comments, you need to log in
The for loop leaves only the last line from the array. Why?
Good day!
I've been asking this question for a long time, but so far no one has answered me. In my telegram bot, the for loop iterates over only the last line from the array. I use the library for telegram bots "Aiogram".
Here is the code:
keyboard = types.InlineKeyboardMarkup()
foods = ['Бургер', 'Картофель', 'Куринные ножки']
for food in foods:
inline_btns = types.InlineKeyboardButton(food, callback_data=food)
keyboard.add(inline_btns)
@dp.callback_query_handler(lambda c: c.data == food) # В food попадает лишь последняя строка из массива.
async def process_callback(call: types.CallbackQuery):
await bot.edit_message_text(text=f"Нажата кнопка {food}", chat_id=call.message.chat.id,
message_id=call.message.message_id)
await message.answer("Выберите блюдо:", reply_markup=keyboard)
Answer the question
In order to leave comments, you need to log in
Works exactly as it should. Because Python is a dynamic language. To understand the problem, you need to understand exactly how functions and their arguments work. (1) normal arguments are resolved at function call time, (2) default arguments are resolved at function definition time, (3) non-local variables within a function are resolved at function runtime (look up in external or global namespaces). I can’t figure out what word to choose instead of “resolve”. Here is the third option and it works in the above code, but the second one should work.
Therefore, it is necessary to write not like this:
lambda c: c.data == food
but like this:
lambda c, food=food: c.data == food
Well, a simple example for reproducing such an effect:
from typing import List
def f_1(lst: List) -> None:
funcs = list()
for val in lst:
funcs.append(lambda: val)
# цикл закончился, val имеет значение последнего элемента из списка
for func in funcs:
print(func())
def f_2(lst: List) -> None:
funcs = list()
for val in lst:
funcs.append(lambda val=val: val)
for func in funcs:
print(func())
if __name__ == '__main__':
data = ['apple', 'tomato', 'potato']
print("\nf_1:")
f_1(data)
print("\nf_2:")
f_2(data)
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question