Frage

Wie kann ich die Klasse erhalten, das eine Methode in Python definiert?

Ich würde das folgende Beispiel drucken möchten "__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)
War es hilfreich?

Lösung

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

Andere Tipps

Danke Sr2222 für den Hinweis auf ich den Punkt fehlt ...

Hier ist der korrigierte Ansatz, der genau wie Alex 'ist aber nicht erforderlich, etwas zu importieren. Ich glaube nicht, es aber eine Verbesserung ist, es sei denn es eine große Hierarchie der geerbten Klassen ist, da dieser Ansatz, sobald der definierenden Klasse stoppt gefunden wird, statt das gesamte Erbe der Rückkehr als getmro tut. Wie gesagt, dies ist ein sehr unwahrscheinliches Szenario.

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

Und das Beispiel:

>>> 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 Lösung liefert die gleichen Ergebnisse. Solange Alex Ansatz verwendet werden kann, würde ich es statt dieser ein verwenden.

Ich weiß nicht, warum niemand jemals erzogen hat oder warum die Top-Antwort hat 50 upvotes, wenn es langsam wie die Hölle ist, aber Sie können auch Folgendes tun:

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

Für Python 3 Ich glaube, das geändert, und Sie werden in .__qualname__ suchen.

Ich begann etwas zu tun, etwas ähnlich, im Grunde die Idee war die Überprüfung, wenn ein Verfahren in einer Basisklasse in einer Unterklasse implementiert worden ist oder nicht. Es stellte sich heraus, wie ich es ursprünglich tat ich konnte nicht erkennen, wenn eine Zwischenklasse tatsächlich wurde das Verfahren implementiert.

für sie meine Abhilfe war eigentlich ganz einfach; eine Methode Attribut Einstellung und später seine Anwesenheit zu testen. Hier ist eine Vereinfachung der ganzen Sache:

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:. Eigentlich method() von run_method() nennen (? Ist nicht, dass der Geist) und haben es alle Argumente unverändert an die Methode übergeben

P. S .: Diese Antwort nicht direkt die Frage beantworten. IMHO gibt es zwei Gründe, die man möchte wissen, welche Klasse eine Methode definiert; erste ist, die Finger in einer Klasse in Debug-Code (wie beispielsweise in die Ausnahmebehandlung) Punkt, und das zweite ist, um zu bestimmen, ob das Verfahren neu implementiert wurde (wobei ein Stub-Methode vom Programmierer implementiert werden gemeint ist). Diese Antwort löst den zweiten Fall in einer anderen Weise.

In Python 3, wenn Sie das tatsächliche Klassenobjekt benötigen, können Sie tun:

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

Wenn die Funktion zu einer verschachtelten Klasse gehören könnten Sie müßten laufen wie folgt:

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
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top