Programing

메서드를 정의한 클래스 가져 오기

crosscheck 2020. 10. 25. 11:37
반응형

메서드를 정의한 클래스 가져 오기


파이썬에서 메서드를 정의한 클래스를 어떻게 얻을 수 있습니까?

다음 예제에서 " __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)

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에게 감사드립니다 ...

다음은 Alex와 비슷하지만 아무것도 가져올 필요가없는 수정 된 접근 방식입니다. 이 접근 방식은 전체 상속을 반환하는 대신 정의 클래스가 발견 되 자마자 중지되므로 상속 된 클래스의 거대한 계층 구조가없는 한 개선이라고 생각 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 솔루션은 동일한 결과를 반환합니다. Alex 접근 방식을 사용할 수있는 한이 방법 대신 사용합니다.


I don't know why no one has ever brought this up or why the top answer has 50 upvotes when it is slow as hell, but you can also do the following:

def get_class_that_defined_method(meth):
    return meth.im_class.__name__

For python 3 I believe this changed and you'll need to look into .__qualname__.


I started doing something somewhat similar, basically the idea was checking whenever a method in a base class had been implemented or not in a sub class. Turned out the way I originally did it I could not detect when an intermediate class was actually implementing the method.

My workaround for it was quite simple actually; setting a method attribute and testing its presence later. Here's an simplification of the whole thing:

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: Actually call method() from run_method() (isn't that the spirit?) and have it pass all arguments unmodified to the method.

P.S.: This answer does not directly answer the question. IMHO there are two reasons one would want to know which class defined a method; first is to point fingers at a class in debug code (such as in exception handling), and the second is to determine if the method has been re-implemented (where method is a stub meant to be implemented by the programmer). This answer solves that second case in a different way.


In Python 3, if you need the actual class object you can do:

import sys
f = Foo.my_function
vars(sys.modules[f.__module__])[f.__qualname__.split('.')[0]]  # Gets Foo object

If the function could belong to a nested class you would need to iterate as follows:

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

참고URL : https://stackoverflow.com/questions/961048/get-class-that-defined-method

반응형