Get-Klasse, die Methode definiert
-
12-09-2019 - |
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)
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