Я действительно удивлен, что никто не выполнил проницательную интроспекцию, предлагаемую 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
.
Для меня правильным было бы это сделать. Либо ajax
, либо ajaxSetup
. Если вы действительно хотите использовать get
, а не использовать ajaxSetup
, тогда вы можете создать свой собственный параметр и дать ему значение текущей даты / времени.
Я бы, однако, поставил под сомнение ваши мотивы в не используя один из других методов.
Добавьте параметр самостоятельно.
$.get(url,{ "_": $.now() }, function(rdata){
console.log(rdata);
});
Начиная с jQuery 3.0 вы можете сделать это:
$.get({
url: url,
cache: false
}).then(function(rdata){
console.log(rdata);
});
Обратите внимание, что синтаксис обратного вызова устарел :
Уведомление об изъятии
Параметры jqXHR.success (), jqXHR.error () и Методы обратного вызова jqXHR.complete (), введенные в jQuery 1.5, устарели из jQuery 1.8. Чтобы подготовить код для их возможного удаления, вместо этого используйте jqXHR.done (), jqXHR.fail () и jqXHR.always ().
blockquote>Здесь модернизированное решение с использованием
promise
интерфейс$.ajax({url: "...", cache: false}).done(function( data ) { // data contains result }).fail(function(err){ // error });
Я очень опаздываю в игре, но это может помочь другим. Я столкнулся с этой проблемой с $ .get, и я не хотел слепо отключать кеширование, и мне не нравился патч timestamp. Поэтому после небольшого исследования я обнаружил, что вы можете просто использовать $ .post вместо $ .get, который НЕ использует кеширование. Просто как тот. :)
Установить кеш: false в вызове jQuery.get с использованием метода ниже
использовать новый Date().getTime(),
, который избежит коллизий, если у вас не будет несколько запросов, происходящих в пределах одной миллисекунды.
Или
Ниже будут запрещены кэширование всех будущих запросов AJAX, независимо от того, какой метод jQuery вы используете ($ .get, $ .ajax и т. д.).
$.ajaxSetup({ cache: false });
В документации JQuery, .get()
принимает только параметры url
, data
(контент), dataType
и success
в качестве своих параметров. То, что вы действительно хотите сделать, это изменить объект jqXHR до его отправки. С помощью .ajax()
это делается с помощью метода beforeSend()
. Но так как .get()
является ярлыком, он не позволяет его.
. Следует, однако, относительно легко переключать вызовы .ajax()
на .get()
. В конце концов, .get()
является всего лишь подмножеством .ajax()
, поэтому вы можете использовать все значения по умолчанию для .ajax()
(за исключением, конечно, для beforeSend()
).
Редактировать:
:: Смотрит на ответ Jivings ::
О да, забыл о параметре cache
! Хотя beforeSend()
полезна для добавления других заголовков, встроенный параметр cache
здесь намного проще.