Как остановить шаблоны кэширования усов [duplicate]

Почему вы не интроспективно?

Я действительно удивлен, что никто не выполнил проницательную интроспекцию, предлагаемую Python (2 и 3 применяются) на вызываемые объекты.

Учитывая небольшую небольшую функцию func, определенную как:

>>> def func(a = []):
...    a.append(5)

Когда Python сталкивается с ней, первое, что он сделает, это скомпилировать ее, чтобы создать code объект для этой функции. Хотя этот шаг компиляции выполнен, Python оценивает *, а затем сохраняет аргументы по умолчанию (пустой список [] здесь) в самом объекте функции . Как упоминалось выше, список a теперь можно считать членом функции func.

Итак, давайте сделаем некоторые интроспекции, до и после изучите, как список расширяется внутри объекта функции. Я использую для этого Python 3.x, для Python 2 это применимо (используйте __defaults__ или func_defaults в Python 2, да, два имени для одной и той же вещи).

Функция перед исполнением:

>>> def func(a = []):
...     a.append(5)
...     

После того, как Python выполнит это определение, он будет принимать любые заданные по умолчанию параметры (a = [] здесь) и вставить их в атрибут __defaults__ для объекта функции (соответствующий section: Callables):

>>> func.__defaults__
([],)

Хорошо, поэтому пустой список как единственная запись в __defaults__, как и ожидалось.

Функция после выполнения:

Теперь приступим к выполнению этой функции:

>>> func()

Теперь давайте посмотрим на те __defaults__ еще раз:

>>> func.__defaults__
([5],)

Удивительно? Значение внутри объекта меняется! Последовательные вызовы функции теперь просто присоединяются к этому встроенному объекту list:

>>> func(); func(); func()
>>> func.__defaults__
([5, 5, 5, 5],)

Итак, у вас есть причина, по которой этот «недостаток» потому что аргументы по умолчанию являются частью объекта функции. Здесь нет ничего странного. Все это немного удивительно.

Общее решение для борьбы с этим - обычное None как значение по умолчанию, а затем инициализируется в теле функции:

def func(a = None):
    # or: a = [] if a is None else a
    if a is None:
        a = []

Поскольку тело функции выполняется заново каждый раз, вы всегда получаете новый новый пустой список, если для a не передан аргумент.


Чтобы еще раз убедиться, что список из __defaults__ совпадает с тем, что используется в функции func, вы можете просто изменить свою функцию, чтобы вернуть id списка a, используемого внутри тела функции. Затем сравните его со списком в __defaults__ (позиция [0] в __defaults__), и вы увидите, как они действительно ссылаются на один и тот же экземпляр списка:

>>> def func(a = []): 
...     a.append(5)
...     return id(a)
>>>
>>> id(func.__defaults__[0]) == func()
True

Все с сила самоанализа!


* Чтобы убедиться, что Python оценивает аргументы по умолчанию при компиляции функции, попробуйте выполнить следующее:

def bar(a=input('Did you just see me without calling the function?')): 
    pass  # use raw_input in Py2

, как вы заметили, input() вызывается перед процессом построения функции и связыванием ее с именем bar.

66
задан Barka 12 January 2012 в 23:47
поделиться

7 ответов

Для меня правильным было бы это сделать. Либо ajax, либо ajaxSetup. Если вы действительно хотите использовать get, а не использовать ajaxSetup, тогда вы можете создать свой собственный параметр и дать ему значение текущей даты / времени.

Я бы, однако, поставил под сомнение ваши мотивы в не используя один из других методов.

35
ответ дан James Montagne 21 August 2018 в 02:26
поделиться
  • 1
    Стоит отметить, что в моем конкретном приложении я использую кеш: false в ajaxSetup (большинство моих вызовов относится к конечным точкам json для полезных нагрузок), а затем я использую $ .ajax (..., cache: true) для любых конкретных шаблонов или вещей что я хочу кэшировать. Я предпочитаю это в любом случае, так как это делает вещи довольно явными, и я вызываю больше вызовов полезной нагрузки, чем статические данные. – David 16 February 2013 в 21:23
63
ответ дан Jivings 21 August 2018 в 02:26
поделиться

Добавьте параметр самостоятельно.

$.get(url,{ "_": $.now() }, function(rdata){
  console.log(rdata);
});

Начиная с jQuery 3.0 вы можете сделать это:

$.get({
  url: url, 
  cache: false
}).then(function(rdata){
  console.log(rdata);
});
87
ответ дан Kevin B 21 August 2018 в 02:26
поделиться

Обратите внимание, что синтаксис обратного вызова устарел :

Уведомление об изъятии

Параметры jqXHR.success (), jqXHR.error () и Методы обратного вызова jqXHR.complete (), введенные в jQuery 1.5, устарели из jQuery 1.8. Чтобы подготовить код для их возможного удаления, вместо этого используйте jqXHR.done (), jqXHR.fail () и jqXHR.always ().

Здесь модернизированное решение с использованием promise интерфейс

$.ajax({url: "...", cache: false}).done(function( data ) {
    // data contains result
}).fail(function(err){
    // error
});
1
ответ дан mar10 21 August 2018 в 02:26
поделиться

Я очень опаздываю в игре, но это может помочь другим. Я столкнулся с этой проблемой с $ .get, и я не хотел слепо отключать кеширование, и мне не нравился патч timestamp. Поэтому после небольшого исследования я обнаружил, что вы можете просто использовать $ .post вместо $ .get, который НЕ использует кеширование. Просто как тот. :)

1
ответ дан RitchieD 21 August 2018 в 02:26
поделиться
  • 1
    Я тоже опаздываю :) Спасибо за ваш вклад, он отлично работает – Angel M. 3 September 2015 в 09:23
  • 2
    Это плохой совет, поскольку GET и POST - разные глаголы и должны использоваться для разных вещей. Тот же URL-адрес сервера может быть отфильтрован по глаголу, поэтому, например, POST не будет работать, если сервер ожидает только GET. Или, что еще хуже, сервер может иметь разные типы поведения для GET и POST (что очень часто на самом деле). – Andrew 7 January 2018 в 09:53

Установить кеш: false в вызове jQuery.get с использованием метода ниже

использовать новый Date().getTime(),, который избежит коллизий, если у вас не будет несколько запросов, происходящих в пределах одной миллисекунды.

Или

Ниже будут запрещены кэширование всех будущих запросов AJAX, независимо от того, какой метод jQuery вы используете ($ .get, $ .ajax и т. д.).

$.ajaxSetup({ cache: false });
2
ответ дан Sangeet Shah 21 August 2018 в 02:26
поделиться

В документации JQuery, .get() принимает только параметры url, data (контент), dataType и success в качестве своих параметров. То, что вы действительно хотите сделать, это изменить объект jqXHR до его отправки. С помощью .ajax() это делается с помощью метода beforeSend(). Но так как .get() является ярлыком, он не позволяет его.

. Следует, однако, относительно легко переключать вызовы .ajax() на .get(). В конце концов, .get() является всего лишь подмножеством .ajax(), поэтому вы можете использовать все значения по умолчанию для .ajax() (за исключением, конечно, для beforeSend()).

Редактировать:

:: Смотрит на ответ Jivings ::

О да, забыл о параметре cache! Хотя beforeSend() полезна для добавления других заголовков, встроенный параметр cache здесь намного проще.

7
ответ дан Thomas Kelley 21 August 2018 в 02:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: