Seite 1 von 1

Methoden in Objecten finden

Verfasst: Mittwoch 13. Juni 2018, 17:31
von monaid
Hallo MitForisten,

ich versuche mir alle __doc__ in Klassen ausgeben zu lassen, und komme nicht weiter.

Code: Alles auswählen


class A(object):
  
    
   def list_helps(self):
     """ print all available commands"""
     className = type(self)
     for m in className.__dict__:
       if not m.startswith('_'):
	 print (className.__dict__[m].__doc__)

class B(A):
   def testFn(self):
     """ this is a test""" 
     pass

a = A()
a.list_helps()
b= B()
b.list_helps()


Die Ausgabe ist:

print all available commands
this is a test

b.list_helps
gibt mir also keine __doc__ von a aus. Offensichtlich habe ich die Vererbung nicht verstanden.
Wie kann man sowas machen ?

Re: Methoden in Objecten finden

Verfasst: Mittwoch 13. Juni 2018, 17:59
von narpfel
Moin,

es sieht so aus, als wolltest du die Builtin-Funktion `help` nachprogrammieren. Machst du das, um zu lernen, oder willst du das wirklich benutzen?

Das funktioniert so nicht, wie du das geschrieben hast, weil die Klasse `B` kein `"list_helps"` in ihrem `__dict__` hat. Klassen haben nur die eigenen Attribute in ihrem `__dict__`. Wenn jetzt auf einer Instanz einer Klasse ein Attribut abgefragt wird, das nicht in der Instanz oder der Klasse der Instanz vorhanden ist, so wird die Vererbungshierarchie der Klasse nach oben hin abgesucht. Die Stichworte wäre MRO und C3-Linearisierung. Das ganze ist näher in Data Model beschrieben.

Re: Methoden in Objecten finden

Verfasst: Mittwoch 13. Juni 2018, 18:02
von __blackjack__
Du müsstest Dich halt selbst durch die Vererbungshierarchie hangeln, denn das `__dict__` von `B` enthält nur die Sachen die in `B` definiert sind. Oder weniger, denn nicht alles muss in dem Attribut stecken! Ein Grund nicht selbst auf die ”magischen” Attribute zuzugreifen. Schau Dir mal die `dir()`-Funktion an. Da bekommst Du nicht nur von `B` beide Methoden, sondern sogar von `b`:

Code: Alles auswählen

In [40]: dir(B)
Out[40]: 
['__class__',
 '__delattr__',
 '__dict__',
 '__doc__',
 '__format__',
 '__getattribute__',
 '__hash__',
 '__init__',
 '__module__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__',
 'list_helps',
 'testFn']

In [41]: dir(b)
Out[41]: 
['__class__',
 '__delattr__',
 '__dict__',
 '__doc__',
 '__format__',
 '__getattribute__',
 '__hash__',
 '__init__',
 '__module__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__',
 'list_helps',
 'testFn']
Der Name `className` ist falsch, denn das ist nicht der Name der der Klasse, sondern tatsächlich die Klasse selbst! Da `class` als Name nicht geht ist die übliche Konvention einen Unterstrich anzuhängen: `class_`. Ausnahme sind Klassen die bei Methoden für `classmethod()` übergeben werden — das Argument heisst dort üblicherweise `cls`.

Vielleicht magst Du Dir auch mal das `inspect`-Modul anschauen:

Code: Alles auswählen

In [46]: inspect.getmembers(b, inspect.ismethod)
Out[46]: 
[('list_helps',
  <bound method B.list_helps of <__main__.B object at 0x7f0f1e628250>>),
 ('testFn', <bound method B.testFn of <__main__.B object at 0x7f0f1e628250>>)]
Und `inspect.getdoc()` ist vielleicht auch interessant.

Edit: Und das `pydoc`-Modul ist vielleicht auch interessant, denn darauf baut die eingebaute `help()`-Funktion auf.

Re: Methoden in Objecten finden

Verfasst: Mittwoch 13. Juni 2018, 19:32
von monaid
Danke für Eure Hilfestellungen,
ja ich wollte das wirklich benutzen (und ich mache das, um zu lernen).

ich will SocketServer.StreamRequestHandler ein Object mitgeben, bei dem alle möglichen Actionen methoden sind, welche mit process_ beginnen. Um mir dynamisch alle Möglichkeiten (mit Erklärung) ausgeben zu lassen dachte ich dies wäre ein probates Mittel.

Angefangen habe ich wirklich auch mit

Code: Alles auswählen

for m in dir (A):
   print A.__dict__[m].__doc_
da kam ich aber vom der hardcoded Klasse nicht los, was die Methode ja nicht sinnvoll vererbar macht.
Danke auch für die Tips mit den Namenskonventionen, ich werde das in Zukunft versuchen zu beachten.
Leider komme ich erst Freitag dazu mir das anzuschauen, Euch noch schönen Abend :)

Re: Methoden in Objecten finden

Verfasst: Mittwoch 13. Juni 2018, 21:14
von __blackjack__
Bei dem Code musst Du vorsichtig sein, denn nicht alles was `dir()` liefert muss auch im `__dict__()` sein. Wie gesagt, diese magischen Namen möglichst vermeiden wenn es einen anderen offiziellen weg gibt. Wenn Du das nicht fest an der Klasse haben willst, kannst in einer Methode ja `self` statt `A` verwenden. Und statt direktem Zugriff auf das `__dict__` das jeweilige Attribut mit der offiziellen Funktion zum Abfragen von Attributen abfragen:

Code: Alles auswählen

        # ...
        for name in dir(self):
            try:
                print(getattr(self, name).__doc__)
            except AttributeError:
                pass

Re: Methoden in Objecten finden

Verfasst: Donnerstag 14. Juni 2018, 05:09
von monaid
Hey Danke _blackjack_,
das hat mir schon sehr geholfen.
getatttr() hatte ich vorher nicht auf dem Schirm, wohl auch deswegen sind meine Versuche vorher gescheitert.
Morgen baue ich das mal ein :)