Мне легче запомнить, как это работает, тогда я могу выяснить какую-то конкретную комбинацию пуска / остановки / шага.
Поучительно сначала понять range()
:
def range(start=0, stop, step=1): # illegal syntax, but that's the effect
i = start
while (i < stop if step > 0 else i > stop):
yield i
i += step
Начните с start
, приращение на step
, не достиг stop
. Очень просто.
Вещь, которую следует помнить об отрицательном шаге, заключается в том, что stop
всегда является исключенным концом, будь то выше или ниже. Если вы хотите, чтобы один и тот же срез находился в противоположном порядке, намного проще делать разворот отдельно: например. 'abcde'[1:-2][::-1]
срезает один символ слева, два справа, затем меняет направление. (См. Также reversed()
.)
Последовательность разреза такая же, за исключением того, что она сначала нормализует отрицательные индексы и никогда не может выйти за пределы последовательности:
TODO : В приведенном ниже коде была ошибка с «никогда не выходить за пределы последовательности», когда abs (шаг)> 1; Я думаю, Я исправил его правильно, но это трудно понять.
def this_is_how_slicing_works(seq, start=None, stop=None, step=1):
if start is None:
start = (0 if step > 0 else len(seq)-1)
elif start < 0:
start += len(seq)
if not 0 <= start < len(seq): # clip if still outside bounds
start = (0 if step > 0 else len(seq)-1)
if stop is None:
stop = (len(seq) if step > 0 else -1) # really -1, not last element
elif stop < 0:
stop += len(seq)
for i in range(start, stop, step):
if 0 <= i < len(seq):
yield seq[i]
Не беспокойтесь о деталях is None
- просто помните, что опускание start
и / или stop
всегда делает правильную вещь, чтобы дать вам целую последовательность.
Нормализовать отрицательные индексы сначала позволяет запускать и / или останавливаться, чтобы считаться с конца независимо: 'abcde'[1:-2] == 'abcde'[1:3] == 'bc'
, несмотря на range(1,-2) == []
, Нормализацию иногда называют «по модулю длины», но обратите внимание, что она добавляет длину только один раз: например. 'abcde'[-53:42]
- это целая строка.
Чтобы AJAX смог «дождаться, пока страница будет отображаться», на самом деле нужно будет полностью обработать страницу, извлечь и запустить все включенные файлы CSS и javascript. Это непросто и не рекомендуется. К счастью, вам все равно не нужно это делать.
Вот три лучших способа подхода к этой проблеме:
GM_xmlhttpRequest()
, чтобы напрямую извлекать только данные полезной нагрузки, а не пытаться проанализировать страницу ресурсов. Иногда этот процесс довольно прост, но для некоторых сайтов требуется сложное взаимодействие и / или аутентификация. postMessage()
. Этот подход почти всегда будет работать, хотя вам, возможно, придется помешать некоторым страницам пытаться «выкинуть» iframe.
Сценарии Greasemonkey будут запускаться как на обычной странице, так и на страницах внутри iframe. Фактически, вы можете установить один и тот же сценарий для работы как на двух, так и на нескольких доменах.
Если главная страница и страница ресурса iframed оба сценария сценариев GM, экземпляры сценария могут связываться друг с другом, кросс-домен, используя postMessage()
.
Например, предположим, что у нас есть сайт, fiddle.jshell.net/9ttvF/show , который содержит данные о путешествии, и мы хотим mash-up , чтобы сайт с соответствующими данными с ресурсного сайта , jsbin.com/ahacab , который использует AJAX для получения своих полезных данных.
Целевой (основной) сайт выглядит так: [/g13]
Сначала сайт ресурса выглядит следующим образом: [/g14]
Затем заканчивается следующим образом: [/g15]
Следующий скрипт:
// ==UserScript==
// @name _Cross-site, AJAX scrape demo
// @include http://fiddle.jshell.net/9ttvF/show/
// @include http://jsbin.com/ahacab*
// @require http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js
// @require https://gist.github.com/raw/2625891/waitForKeyElements.js
// @grant GM_addStyle
// ==/UserScript==
if (/fiddle\.jshell\.net/i.test (location.host) ) {
console.log ("***Master-page start...");
/*--- Inform the user.
*/
$("#plainResults").before (
'<div id="gmFetchRez">Greasemonkey is fetching results from jsbin.com...</div>'
);
/*--- Setup to process messages from the GM instance running on the iFrame:
*/
window.addEventListener ("message", receiveMessage, false);
/*--- Load the resource site in a hidden iframe.
*/
$("body").append ('<iframe src="http://jsbin.com/ahacab" id="gmIframe"></iframe>');
}
else {
console.log ("***Framed start...");
/*--- Wait for the AJAXed-in content...
*/
waitForKeyElements ("#results table.rezTable", sendResourcePageData);
}
function sendResourcePageData (jNode) {
console.log ("Results found! Sending them to the main window...");
window.top.postMessage (jNode.html(), "*");
}
function receiveMessage (event) {
if (event.origin != "http://jsbin.com") return;
$("#gmFetchRez").html (event.data);
}
//--- Use CSS to control appearances.
GM_addStyle ( " \
#gmIframe { \
display: none; \
} \
#gmFetchRez { \
background: lightYellow; \
border: 3px double red; \
padding: 1em; \
} \
" );
Окончательный результат выглядит следующим образом: скрипт установлен и запущен: [/g16]