Есть ли способ получить доступ к классу метода, когда все, что у вас есть, является вызываемым

У меня есть код, похожий на:

class Foo:
    def foo(self):
        pass


class Bar:
    def foo(self):
        pass

f = random.choice((Foo().foo, Bar().foo))

Как мне получить доступ к Bar или Foo из f?

f.__dict__ имеет мало пользы, но поскольку repr(f) дает <bound method Bar.foo of <__main__.Bar object at 0x10c6eec18>>', это должно быть возможно, но как?

Ответ 1

Каждый связанный метод имеет атрибут __self__, который является

экземпляр

к которому привязан этот метод, или None

(скопировано из здесь)

Подробнее о связанных методах (из Модель данных):

Если вы обращаетесь к методу (функции, определенной в пространстве имен классов) через экземпляр вы получаете специальный объект: связанный метод (также).... Связанные методы имеют два специальных атрибуты только для чтения: m.__self__ - это объект, на котором метод работает...

Итак, f.__self__ предоставит вам экземпляр класса:

print(f.__self__) # <__main__.Foo object at 0x7f766efeee48>

И type(f.__self__) или f.__self__.__class__ получит объект типа:

print(type(f.__self__)) # <class '__main__.Foo'>

Вы использовали бы __class__ для классов старого стиля.