Получить класс, который определил метод
Как я могу получить класс, который определил метод в Python?
Я бы хотел, чтобы следующий пример напечатал "__main__.FooClass
":
class FooClass:
def foo_method(self):
print "foo"
class BarClass(FooClass):
pass
bar = BarClass()
print get_class_that_defined_method(bar.foo_method)
4 ответа:
import inspect def get_class_that_defined_method(meth): for cls in inspect.getmro(meth.im_class): if meth.__name__ in cls.__dict__: return cls return None
спасибо Sr2222 за указание, что я упустил суть...
вот исправленный подход, который так же, как у Алекса, но не требует ничего импортировать. Я не думаю, что это улучшение, хотя, если нет огромной иерархии унаследованных классов, поскольку этот подход останавливается, как только определяющий класс найден, вместо того, чтобы возвращать все наследование как
getmro
делает. Как уже было сказано, это очень маловероятный сценарий.def get_class_that_defined_method(method): method_name = method.__name__ if method.__self__: classes = [method.__self__.__class__] else: #unbound method classes = [method.im_class] while classes: c = classes.pop() if method_name in c.__dict__: return c else: classes = list(c.__bases__) + classes return None
и Пример:
>>> class A(object): ... def test(self): pass >>> class B(A): pass >>> class C(B): pass >>> class D(A): ... def test(self): print 1 >>> class E(D,C): pass >>> get_class_that_defined_method(A().test) <class '__main__.A'> >>> get_class_that_defined_method(A.test) <class '__main__.A'> >>> get_class_that_defined_method(B.test) <class '__main__.A'> >>> get_class_that_defined_method(C.test) <class '__main__.A'> >>> get_class_that_defined_method(D.test) <class '__main__.D'> >>> get_class_that_defined_method(E().test) <class '__main__.D'> >>> get_class_that_defined_method(E.test) <class '__main__.D'> >>> E().test() 1
решение Alex возвращает те же результаты. Пока можно использовать подход Алекса, я бы использовал его вместо этого.
Я не знаю, почему никто никогда не поднимал этот вопрос или почему верхний ответ имеет 50 upvotes, когда он медленный, как ад, но вы также можете сделать следующее:
def get_class_that_defined_method(meth): return meth.im_class.__name__
для python 3 я считаю, что это изменилось, и вам нужно будет заглянуть в
.__qualname__
.
Я начал делать что-то похожее, в основном идея заключалась в проверке всякий раз, когда метод в базовом классе был реализован или нет в подклассе. Оказалось, что я изначально сделал это, я не мог обнаружить, когда промежуточный класс фактически реализовывал метод.
мой обходной путь для этого был довольно прост на самом деле; установка метода атрибут и проверка его присутствия позже. Вот упрощение всего вещь:
class A(): def method(self): pass method._orig = None # This attribute will be gone once the method is implemented def run_method(self, *args, **kwargs): if hasattr(self.method, '_orig'): raise Exception('method not implemented') self.method(*args, **kwargs) class B(A): pass class C(B): def method(self): pass class D(C): pass B().run_method() # ==> Raises Exception: method not implemented C().run_method() # OK D().run_method() # OK
обновление: на самом деле вызов
method()
Сrun_method()
(разве это не дух?) и пусть он передаст все аргументы без изменений в метод.P. S.: Данный ответ не прямо ответить на вопрос. IMHO есть две причины, по которым нужно знать, какой класс определил метод; Во-первых, указать пальцем на класс в отладочном коде (например, в обработке исключений), а во-вторых, определить, был ли метод повторно реализован (где метод-это заглушка для реализации программистом). Этот ответ решает этот второй случай по-другому.