>>> class A(object): pass
>>> def func(cls): pass
>>> A.func = func
>>> A.func
<unbound method A.func>
Как это присвоение создает метод? Это кажется неинтуитивным, что присвоение делает следующее для классов:
classmethod()
в методы класса (на самом деле, это довольно интуитивно),staticmethod()
в функцииКажется, что для первого, должно быть instancemethod()
, и для последнего, не должно быть функции обертки вообще. Я понимаю, что это для использования в a class
блок, но почему они должны применяться за пределами него?
Но что еще более важно, как точно делает присвоение функции в работу класса? Какое волшебство происходит, который разрешает те 3 вещи?
Еще более сбивающий с толку с этим:
>>> A.func
<unbound method A.func>
>>> A.__dict__['func']
<function func at 0x...>
Но я думаю, что это - что-то, чтобы сделать с дескрипторами при получении атрибутов. Я не думаю, что это имеет непосредственное отношение к установке атрибутов здесь.
Вы правы, что это имеет отношение к протоколу дескрипторов. Дескрипторы - это то, как в Python реализована передача объекта-приемника в качестве первого параметра метода. Более подробно о поиске атрибутов в Python вы можете прочитать здесь. Ниже показано на более низком уровне, что происходит, когда вы делаете A.func = func; A.func:
# A.func = func
A.__dict__['func'] = func # This just sets the attribute
# A.func
# The __getattribute__ method of a type object calls the __get__ method with
# None as the first parameter and the type as the second.
A.__dict__['func'].__get__(None, A) # The __get__ method of a function object
# returns an unbound method object if the
# first parameter is None.
a = A()
# a.func()
# The __getattribute__ method of object finds an attribute on the type object
# and calls the __get__ method of it with the instance as its first parameter.
a.__class__.__dict__['func'].__get__(a, a.__class__)
# This returns a bound method object that is actually just a proxy for
# inserting the object as the first parameter to the function call.
Таким образом, именно поиск функции в классе или экземпляре превращает ее в метод, а не присвоение ее атрибуту класса.
classmethod
и staticmethod
- это просто немного разные дескрипторы, classmethod возвращает связанный объект метода, привязанный к объекту типа, а staticmethod просто возвращает исходную функцию.
Пункт 1: Функция func
, которую вы определили, существует как объект первого класса в Python.
Пункт 2: Классы в Python хранят свои атрибуты в __dict__
.
Что же происходит, когда вы передаете функцию в качестве значения атрибута класса в Python? Эта функция хранится в __dict__
класса, что делает ее методом класса, доступ к которому осуществляется вызовом имени атрибута, которому вы ее присвоили.
Нужно учитывать, что в Python все является объектом. Установив это, легче понять, что происходит. Если у вас есть функция def foo(bar): print bar
, вы можете сделать spam = foo
и вызвать spam(1)
, получив, конечно, 1
.
Объекты в Python хранят свои атрибуты экземпляра в словаре под названием __dict__
с "указателем" на другие объекты. Поскольку функции в Python также являются объектами, их можно присваивать и манипулировать ими как простыми переменными, передавать другим функциям и т. д. Реализация объектной ориентации в Python использует это преимущество и рассматривает методы как атрибуты, как функции, которые находятся в __dict__
объекта.
Первым параметром методов экземпляра всегда является сам объект экземпляра, обычно называемый self
(но он может называться this
или banana
). Когда метод вызывается непосредственно на классе
, он не связан ни с каким экземпляром, поэтому в качестве первого параметра вы должны передать ему объект экземпляра (A.func(A())
). Когда вы вызываете связанную функцию (A().func()
), первый параметр метода, self
, является неявным, но за шторами Python делает точно так же, как и при прямом вызове несвязанной функции и передаче объекта экземпляра в качестве первого параметра.
Если это понятно, то тот факт, что присваивание A.func = func
(которое за занавесками делает A.__dict__["func"] = func
) оставляет вас с несвязанным методом, неудивителен.
В вашем примере cls
в def func(cls): pass
на самом деле будет передан экземпляр (self
) типа A
. При применении classmethod
или staticmethod
декораторы делают не что иное, как берут первый аргумент, полученный при вызове функции/метода, и преобразуют его во что-то другое перед вызовом функции.
classmethod
принимает первый аргумент, получает объект class
экземпляра и передает его в качестве первого аргумента при вызове функции, а staticmethod
просто отбрасывает первый параметр и вызывает функцию без него.
Невозможно «подделать» HTTP-запросы. Вы отправляете запрос на сервер, и сервер отвечает соответствующим образом.
Я думаю, что вы пытаетесь предотвратить это спуфинг печенья. Учитывая, что файлы cookie хранятся на стороне клиента, вы ничего не можете сделать, чтобы запретить пользователям изменять их содержимое.
Не храните конфиденциальную информацию в файлах cookie. Они не защищены и легко читаются и изменяются клиентом.
Вместо этого используйте PHP-сеансы. Полное объяснение того, как работают сеансы и как обеспечить их безопасность, можно прочитать в одном из моих предыдущих ответов .
По существу, защита сеансов выполняется на двух фронтах:
Предотвращение фиксации сеанса
Регенерация нового session _ id
каждые X запросов, чтобы уменьшить время, в течение которого злоумышленник должен украсть идентификатор.
Уникальная идентификация клиента
Использование IP и/или агента пользователя для Это действительно единственный два выборе, которые вы должны однозначно определить клиента.
Даже с тем, что на месте, ни одно решение не является дурацким, и как только ваш session _ id
скомпрометирован, вы в значительной степени сделали для.
Для более подробного объяснения см. мой предыдущий ответ .
-121--4779931-(NB, я даю вам два отдельных ответа. Этот вопрос стоит как можно ближе к вашему вопросу.)
Ваш вопрос говорит
while{ count >= mAllPositions.Count )
{
//Run my code here
}
, но я предполагаю, что вы действительно имеете в виду:
while( count < mAllPositions.Count )
; // do nothing -- busy wait until the count has been incremented enough
// Now run my code here
??
Если это так, то вы можете сделать то же самое более эффективно, используя семафор:
Semaphore TheSemaphore = new Semaphore( 0, mAllPositions.Count );
По мере завершения каждого асинхронного вызова, освободить семафор.
TheSemaphore.Release();
Перед выполнением окончательного кода убедитесь, что семафор был освобожден необходимое количество раз:
for( int i=0; i<mAllPositions.Count; i++ )
TheSemaphore.WaitOne();
// Now run follow-on code.
Ваш код будет заблокирован до завершения всех асинхронных операций.
-121--4518350- Дескрипторы - это магические 1 , которые превращают обычную функцию в связанный или несвязанный метод при извлечении ее из экземпляра или класса, поскольку все они являются просто функциями, которые нуждаются в различных стратегиях связывания. Декораторы classmethod
и staticmethod
реализуют другие стратегии связывания, и staticmethod
фактически просто возвращает сырую функцию, которая является тем же поведением, которое вы получаете от объекта, не являющегося функцией вызываемого
.
Для получения дополнительной информации см. «Пользовательские методы» , но обратите внимание на следующее:
Также обратите внимание, что это преобразование происходит только для пользовательских функций; другие вызываемые объекты (и все не вызываемые объекты) извлекаются без преобразования.
Поэтому, если вы хотите, чтобы это преобразование было для вашего собственного вызываемого объекта, вы можете просто обернуть его в функцию, но вы также можете написать дескриптор для реализации вашей собственной стратегии связывания.
Вот статический метод
декоратора в действии,возврат базовой функции при обращении к ней.
>>> @staticmethod
... def f(): pass
>>> class A(object): pass
>>> A.f = f
>>> A.f
<function f at 0x100479398>
>>> f
<staticmethod object at 0x100492750>
Если обычный объект с методом __ call __
не преобразуется:
>>> class C(object):
... def __call__(self): pass
>>> c = C()
>>> A.c = c
>>> A.c
<__main__.C object at 0x10048b890>
>>> c
<__main__.C object at 0x10048b890>
1 Специфическая функция func _ descr _ get
в Objects/funcobject.c .
Относительно комментария MTsoul к ответу Gabriel Hurley:
Разница в том, что func
имеет метод __call__()
, что делает его "вызываемым", т.е. к нему можно применить оператор ()
. Посмотрите документацию Python (поиск по __call__
на этой странице).