Как я могу получить класс, который определил метод в 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)
python
python-2.6
python-datamodel
Джесси Олдридж
источник
источник
Ответы:
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
источник
__dict__
! Иногда__slots__
используется. Вероятно, лучше использоватьgetattr
для проверки, находится ли метод в классе.Python 3
, пожалуйста , обратитесь к этому ответу .'function' object has no attribute 'im_class'
Спасибо 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 возвращает те же результаты. Пока можно использовать подход Алекса, я бы использовал его вместо этого.
источник
Cls().meth.__self__
просто дает вам экземпляр,Cls
который привязан к этому конкретному экземпляруmeth
. Это аналогCls().meth.im_class
. Если у вас естьclass SCls(Cls)
,SCls().meth.__self__
вы получитеSCls
экземпляр, а неCls
экземпляр. OP хочет получитьCls
, что, по-видимому, доступно только при прохождении MRO, как это делает @Alex Martelli.Я не знаю, почему никто никогда не поднимал этот вопрос или почему за лучший ответ 50 голосов, когда он чертовски медленный, но вы также можете сделать следующее:
def get_class_that_defined_method(meth): return meth.im_class.__name__
Я считаю, что для python 3 это изменилось, и вам нужно будет изучить
.__qualname__
.источник
В Python 3, если вам нужен фактический объект класса, вы можете:
import sys f = Foo.my_function vars(sys.modules[f.__module__])[f.__qualname__.split('.')[0]] # Gets Foo object
Если бы функция могла принадлежать к вложенному классу, вам нужно было бы выполнить итерацию следующим образом:
f = Foo.Bar.my_function vals = vars(sys.modules[f.__module__]) for attr in f.__qualname__.split('.')[:-1]: vals = vals[attr] # vals is now the class Foo.Bar
источник
Я начал делать что-то похожее, в основном идея заключалась в том, чтобы проверять, был ли реализован метод в базовом классе или нет в подклассе. Оказалось, как я это делал изначально, я не мог определить, когда промежуточный класс действительно реализовывал метод.
На самом деле мой обходной путь был довольно простым; установка атрибута метода и проверка его наличия позже. Вот упрощение всего:
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
UPDATE: На самом деле звонить
method()
изrun_method()
(не то, что дух?), Они должны передать все аргументы немодифицированных к методу.PS: Этот ответ не дает прямого ответа на вопрос. ИМХО есть две причины, по которым нужно знать, какой класс определяет метод; первый - указать пальцем на класс в отладочном коде (например, при обработке исключений), а второй - определить, был ли метод повторно реализован (где метод - это заглушка, предназначенная для реализации программистом). Этот ответ решает второй случай другим способом.
источник
Python 3
Решил очень просто:
str(bar.foo_method).split(" ", 3)[-2]
Это дает
'FooClass.foo_method'
Разделите на точку, чтобы получить класс и имя функции отдельно
источник