В связанных методах вы можете использовать три специальных параметра только для чтения:
- im_func , который возвращает (несвязанный) функциональный объект
- im_self , который возвращает объект, с которым связана функция (экземпляр класса)
- im_class , который возвращает класс im_self
Тестирование вокруг:
class Test(object):
def foo(self):
pass
instance = Test()
instance.foo # <bound method Test.foo of <__main__.Test object at 0x1>>
instance.foo.im_func # <function foo at 0x2>
instance.foo.im_self # <__main__.Test object at 0x1>
instance.foo.im_class # <__main__.Test class at 0x3>
# A few remarks
instance.foo.im_self.__class__ == instance.foo.im_class # True
instance.foo.__name__ == instance.foo.im_func.__name__ # True
instance.foo.__doc__ == instance.foo.im_func.__doc__ # True
# Now, note this:
Test.foo.im_func != Test.foo # unbound method vs function
Test.foo.im_self is None
# Let's play with classmethods
class Extend(Test):
@classmethod
def bar(cls):
pass
extended = Extend()
# Be careful! Because it's a class method, the class is returned, not the instance
extended.bar.im_self # <__main__.Extend class at ...>
Здесь есть интересная вещь, которая дает вам подсказку о том, как вызываются методы:
class Hint(object):
def foo(self, *args, **kwargs):
pass
@classmethod
def bar(cls, *args, **kwargs):
pass
instance = Hint()
# this will work with both class methods and instance methods:
for name in ['foo', 'bar']:
method = instance.__getattribute__(name)
# call the method
method.im_func(method.im_self, 1, 2, 3, fruit='banana')
По сути, im_self атрибут связанного метода изменяется, чтобы позволить использовать его в качестве первого параметра при вызове im_func