Ну, причина в том, что привязки выполняются при выполнении кода, и выполняется определение функции, ну ... когда функции определены.
Сравните это:
class BananaBunch:
bananas = []
def addBanana(self, banana):
self.bananas.append(banana)
Этот код страдает от такого же неожиданного случая. bananas - это атрибут класса, и, следовательно, когда вы добавляете к нему вещи, он добавляется ко всем экземплярам этого класса. Причина в том, что это точно то же самое.
Это просто «Как это работает», и заставить его работать по-другому в функциональном случае, вероятно, будет сложно, а в случае класса вероятно невозможно или, по крайней мере, замедлить объект создание экземпляра, так как вам придется хранить код класса и выполнять его при создании объектов.
Да, это неожиданно. Но как только пенни падает, она прекрасно вписывается в то, как работает Python в целом. На самом деле, это хорошее учебное пособие, и как только вы поймете, почему это происходит, вы будете намного лучше читать python.
Это говорит о том, что он должен занимать видное место в любом хорошем учебнике Python. Потому что, как вы говорите, все рано или поздно сталкиваются с этой проблемой.
Вы должны создать функцию, которая вызывает себя через 5 секунд
var i=0;
function sendEmailNow() {
SendEmail(i);
++i;
if(i<20) {
setTimeout(sendEmailNow, 5000);
}
}
Ваша петля настраивает 20 таймеров, чтобы подождать 5 секунд, а затем разрешить им все сразу.
Попробуйте что-то вроде этого:
var email_count = 20;
var sendMails = function(){
SendEmail(email_count--);
if(email_count > 0){
setTimeout(sendMails, 5000);
}
}
setTimeout(sendMails, 5000)
Сначала передайте функцию setTimeout
.
Во-вторых, вам будет лучше, если вы установите таймаут для следующего в очереди после завершения текущего.
В цикле for
:
sendEmail(0); // start sending first
и в обратном вызове:
, function(data) {
if(id < 19) { // if next should be sent
setTimeout(function() {
SendEmail(id + 1);
}, 5000);
}
var toAppend = "<span> " + data + "</span>"
$("#sentTo").append(toAppend);
}
var i = 0;
(иначе протекают во внешнюю область или ошибку времени выполнения) window.setTimeout(
(function (j) {
return function () {
sendEmail(j);
};
}(i)),
i * 10000);
sendEmail
(стиль кода: не конструктор) $id
в серверном коде, чтобы предотвратить SQL injection . Случается, что вы вызываете setTimeout 20 раз, сразу после одного, с таймаутом в 5 секунд. Естественно, все электронные письма отправляются сразу. Вы можете изменить цикл, чтобы выглядеть так:
for (i=0;i<20;i++) {
setTimeout("SendEmail("+ i + ")",(i+1)*5000);
}
Однако есть много других вариантов, и они будут зависеть от того, что лучше всего подходит вашей конкретной проблеме.
Используйте интервал вместо цикла.
Рабочая демонстрация: http://jsfiddle.net/xfVa9/2/
$(document).ready(function() {
var tmr;
var i=0;
tmr=setInterval(function(){
if(i<20){
SendEmail(i);
alert("Sent "+i)
i++;
}else{
clearInterval(tmr);
}
},5000)
});
setInterval
. Помните, однако, что i
объявляется глобальной переменной. Вот пример: jsfiddle.net/xfVa9/3
– PPvG
24 December 2011 в 14:39
i
и без выражения функции, см. Другие ответы. Но выражения функций являются важным инструментом, о котором следует узнать. – PointedEars 24 December 2011 в 16:22