Важным моментом является то, что понимание списка создает новый список. Генератор создает повторяемый объект, который будет «фильтровать» исходный материал на лету, когда вы будете использовать биты.
Представьте, что у вас есть файл журнала объемом 2 ТБ, называемый "принц-файлом", и вы хотите, чтобы содержимое и длина были для всех строк, начинающихся со слова "ВХОД".
Таким образом, вы пытаетесь начать с написания списка:
logfile = open("hugefile.txt","r")
entry_lines = [(line,len(line)) for line in logfile if line.startswith("ENTRY")]
Это отрывает весь файл, обрабатывает каждую строку и сохраняет совпадающие строки в вашем массиве. Следовательно, этот массив может содержать до 2 ТБ контента. Это много оперативной памяти, и, вероятно, не практично для ваших целей.
Таким образом, вместо этого мы можем использовать генератор, чтобы применить «фильтр» к нашему контенту. На самом деле никакие данные не читаются, пока мы не начнем итерацию по результату.
logfile = open("hugefile.txt","r")
entry_lines = ((line,len(line)) for line in logfile if line.startswith("ENTRY"))
Из нашего файла еще не было прочитано ни одной строки. Фактически, скажем, мы хотим отфильтровать наш результат еще дальше:
long_entries = ((line,length) for (line,length) in entry_lines if length > 80)
Еще ничего не было прочитано, но мы указали два генератора, которые будут действовать на наши данные, как мы хотим.
Давайте запишем наши отфильтрованные строки в другой файл:
outfile = open("filtered.txt","a")
for entry,length in long_entries:
outfile.write(entry)
Теперь мы читаем входной файл. Поскольку наш цикл for
продолжает запрашивать дополнительные строки, генератор long_entries
запрашивает строки из генератора entry_lines
, возвращая только те, длина которых превышает 80 символов. И, в свою очередь, генератор entry_lines
запрашивает строки (отфильтрованные как указано) от итератора logfile
, который, в свою очередь, читает файл.
Таким образом, вместо того, чтобы «выталкивать» данные в свою функцию вывода в виде полностью заполненного списка, вы даете функции вывода способ «извлекать» данные только тогда, когда это необходимо. В нашем случае это гораздо эффективнее, но не так гибко. Генераторы один путь, один проход; данные из файла журнала, который мы прочитали, немедленно удаляются, поэтому мы не можем вернуться к предыдущей строке. С другой стороны, нам не нужно беспокоиться о сохранении данных, как только мы закончим с ними.
Первый аргумент setTimeout - это функция. Так что заключите ваш код в анонимную функцию, и все готово.
$("form.stock").submit(function(){
// Example Post
$.post($(this).attr('action'), { id: '123', stock: '1' });
var submit = $(this).find(":submit").attr('value','Saved!'); //Creating closure for setTimeout function.
setTimeout(function() { $(submit).attr('value','Update') }, 2000);
return false;
});
Я не могу сейчас протестировать этот код. Сообщите мне, если это не сработает.
РЕДАКТИРОВАТЬ: Как предлагает redsquare, имеет смысл создать закрытие с помощью самой кнопки отправки.
Я бы, возможно, предложил другой (на мой взгляд, лучший) интерфейс для обратной связи, чем изменение текста кнопки. Вы можете использовать виджет jGrowl или dialog для отображения сообщения через обратный вызов из метода post.
$("form.stock").submit(function(){
$.post(
$(this).attr('action'),
{ id: '123', stock: '1' },
function() { $.jGrowl("Your update was successfully saved."); }
);
});
You probably want to wrap the action in a function:
setTimeout(function(){$(this).find(":submit").attr('value', 'Update')}, 2000);
$("form.stock").submit(function(){
var $form = $(this);
$.post( $form.attr('action'), { id: '123', stock: '1' } );
var $submit = $form.find(":submit").attr('value','Saved!');
window.setTimeout(function() {
$submit.attr('value','Update')
}, 2000);
return false;
});