Н.Б .: статические методы не похожи на методы класса!

on документация о операторis говорит:Операторы

 а такжеis тест на идентичность объекта:is not верно тогда и только тогда, когдаx is y а такжеx это один и тот же объект.y дает обратное значение истины.x is not yДавайте попробуем это:

>>> def m():
...   pass
... 
>>> m is m
True

Документация Python также говоритИз-за автоматической сборки мусора, свободных списков и динамической природы дескрипторов вы можете заметить необычное поведение в некоторых случаях:

 оператор, как те, которые включают сравнения между методами экземпляра, или константы. Проверьте их документацию для получения дополнительной информации.isЯ искал больше объяснений, но не смог найти ни одного.

>>> class C:
...   def m():
...     pass
... 
>>> C.m is C.m
False

Почему

 ложный?C.m is C.mЯ использую Python 2.x. Как отмечено в ответах ниже, в Python 3.x

 правда.C.m is C.mКогда вы запрашиваете атрибут экземпляра, который является функцией, вы получаете

Ответы на вопрос(3)

 C.m is C.m все еще ложь). Если вы введете толькоC().m is C().m на REPL, держу пари, вы видите что-то вродеC.m, Оболочка UnboundMethod делает очень мало, кроме проверки<UnboundMethod... >, (Кажется довольно бессмысленным создавать оболочку для этого? Так оно и было отброшено в Python 3 -isinstance(self, cls) это просто функция). Свежий экземпляр оболочки создается по требованию при каждом обращении к методу -C.m создает одно, другоеC.m создает еще один. Так как они разные экземпляры,C.mТесно связаны связанные методы, которые позволяют вам делатьC.m is not C.m.

 но также вызываютf = obj.method; f(*args), После создания экземпляра все функции, определенные в классе (читай: все методы, кроме, конечно, обработанных обезьянами), становятся свойствами экземпляра. Когда вы обращаетесь к ним, вы вместо этого получаете свежий экземпляр оболочки (связанный метод) вокруг простой функции. Эта обертка запоминает экземпляр (instance.method is not instance.method) и когда вызывается сself просто передать их функции - с(arg1, arg2, ..., argN) добавлен в качестве первого аргумента. Обычно вы этого не замечаете, потому что вызываете метод сразу, но это то, что позволяетself неявно, не прибегая к хитрости на уровне языка.selfВидеть

история питона для более подробной информации и, ну, истории.Потому что C.m () не является статическим методом класса C:

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

class C:
    @staticmethod
    def m():
        pass

print C.m is C.m
# True

c = C()
print c.m is C.m
# True

С другой стороны, в вашем примере

 это не статический метод, поэтому Python предполагает, что он должен рассматриваться как нестатический метод, поэтому всякий раз, когда вы вызываетеC.m, он вернет новый экземпляр:C.mН.Б .: статические методы не похожи на методы класса!

class C:
   def m():
      pass

a = C.m
b = C.m

print id(a), id(b)
# 43811616, 43355984
print a is b
# False

Почему метод не идентичен самому

Решение Вопроса

связанный метод: вызываемый объект, который оборачивает функцию, определенную в классе, и передает экземпляр в качестве первого аргумента. В Python 2.x, когда вы запрашиваете атрибут класса, который является функцией, вы получаете аналогичный прокси-объект, называемыйнесвязанный методЭтот специальный объект создается, когда вы запрашиваете его, и, очевидно, нигде не кэшируется. Это означает, что когда вы делаете:

>>> class A: m = lambda: None
...
>>> A.m
<unbound method A.<lambda>>

вы создаете два

>>> A.m is A.m
False

отчетливый несвязанные объекты метода и тестирование их на идентичность.Заметить, что

а также

>>> x = A.m
>>> x is x
True

отлично работает (

>>> A.m.im_func is A.m.im_func
True

 является исходной функцией, которую переносит объект несвязанного метода.)im_funcВ Python 3.x, кстати,

 Истинно, потому что (несколько бессмысленные) прокси-объекты несвязанного метода были полностью удалены, и вы просто получили исходную функцию, которую вы определили.C.m is C.mЭто всего лишь один пример очень динамичной природы поиска атрибутов в Python: когда вы запрашиваете атрибут объекта, можно запустить произвольный Python для вычисления значения этого атрибута. Вот еще один пример, когда ваш тест не пройден, и гораздо понятнее почему:

Для полноты

>>> class ChangingAttribute(object):
...     @property
...     def n(self):
...             self._n += 1
...             return self._n
...
...     def __init__(self):
...             self._n = 0
...
>>> foo = ChangingAttribute()
>>> foo.n
1
>>> foo.n
2
>>> foo.n
3
>>> foo.n is foo.n
False
>>> foo.n
6
 Katriel09 янв. 2011 г., 16:57
Я полагаю, вы используете Python 2? В Python 3__getattr__.
 Jochen Ritzel09 янв. 2011 г., 16:52

Ваш ответ на вопрос