Это очень хороший вопрос.
Чтобы очистить несколько вещей:
- Когда имя метода доступен через класс (например,
B.p
) он сказал, что несвязанный.
- В противном случае доступ к способу через экземпляр его класса (например,
B().p
) считается связанным.
Основное различие между связанной и несвязанного что если связанный, первый аргумент будет неявно экземпляр вызывающего класса. Вот почему мы должны добавить self
в качестве первого аргумента для каждого метода, когда мы его определяем. Когда unbound, вам придется явно передать экземпляр класса, к которому вы хотите применить логику метода.
Например:
class B(object):
def foo(self):
print 'ok'
>>>B().foo()
ok
>>>B.foo()
Exception, missing an argument.
>>>B.foo(B())
ok
Это основное объяснение связанного и несвязанный. Теперь о том, что случилось с __dict__
странностями. Любой объект в Python может определять методы __get__
и __set__
, которые контролируют доступ к ним, когда они являются атрибутами в классе. Они называются дескрипторами .
В простых словах, когда вы получаете доступ к атрибуту (свойству) класса по его экземпляру или классу, Python не возвращает объект напрямую, вместо этого он вызывает метод __get__
или __set__
, который, в свою очередь, возвращает удобный объект для работайте с.
Функции в Python переопределяют этот метод __get__
. Поэтому, когда вы выдаете B.foo
или B().foo
, он возвращает тип instancemethod
, который является оберткой до типа function
(обертка, которая пропускает self
в качестве первого аргумента неявно). Когда вы получаете доступ к функции через словарь raw-класса, нет ответа на __get__
, потому что вы не обращаетесь к ним как к свойству класса, поэтому возвращаемое значение должно быть raw.
Есть много, чтобы сказать об этой теме, я попытался дать очень простой ответ на такой вопрос умный. Вы можете найти окончательный информация о блоге Guido статья The Inside Story on New-Style Classes, очень рекомендуется.
UPDATE: О вашем последнем примере:
>>> B.p
<unbound method B.p>
>>> type(B.p)
<type 'instancemethod'>
Обратите внимание, что интерпретатор языка Python >>>B.p
фактически не печатать тип объекта, а не печатает __repr__
метод объекта. Вы можете проверить это, выполнив >>>print B.p.__repr__()
и увидев, что тот же результат :)
Python's full of untirection and Delegation, вот что делает его настолько гибким.
Надеюсь, что это немного прояснит ситуацию.
Не знаю, почему кто-то занижает этот вопрос. –
@PauloBu Ну, теперь мы двое! –