identifizieren der Argument-Namen einer Methode...

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Benutzeravatar
jens
Moderator
Beiträge: 8482
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Donnerstag 29. September 2005, 19:14

Mit getattr kann ich ja die methode einer Klasse bekommen... Kann man auch rausbekommen, welche Argumente die Klasse erwartet???
Bsp.:

Code: Alles auswählen

class test:
  def test1(self, arg1, arg2):
    print arg1, arg2
Wie bekomme ich raus, das test().test1 die Argumente arg1 und arg2 erwartet? Ich brauche die Namen als Strings...

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
BlackJack

Donnerstag 29. September 2005, 21:37

Das könnte so gehen:

Code: Alles auswählen

In [22]: class test:
   .22.:    def test1(self, arg1, arg2):
   .22.:      print arg1, arg2
   .22.:

In [23]: inspect.getargs(test.test1.im_func.func_code)
Out[23]: (['self', 'arg1', 'arg2'], None, None)
Ich gehe mal davon aus, das das recht CPython-spezifisch ist. Wozu brauchst Du die Namen denn?
Benutzeravatar
jens
Moderator
Beiträge: 8482
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Freitag 30. September 2005, 09:22

Ich wollte das im PyLucid ModulManager einbauen... Allerdings mach ich das am besten einfach mit try und übergebe die Daten auf gut glück ;)
Mal sehen...

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
henning
User
Beiträge: 274
Registriert: Dienstag 26. Juli 2005, 18:37

Freitag 30. September 2005, 10:45

An sowas Ähnlichem bin ich momentan auch dran (siehe aktueller Thread), inspect macht nichts anderes als ein paar Werte einer Funktion auszulesen:

Code: Alles auswählen

>>> class Foo:
...   def my_fn(self, something, irgendwas="default", foo=3.14):
...     lokal = 67
... 
>>> f = Foo()
>>> print f.my_fn.im_func.func_code.co_argcount
4
>>> print f.my_fn.im_func.func_code.co_varnames 
('self', 'something', 'irgendwas', 'foo','lokal')
>>> print f.my_fn.im_func.func_defaults
('default', 3.1400000000000001)
Also man kann schon ne ganze Menge über ne Funktion rauskriegen, ohne sie aufzurufen und sogar, ohne das inspect-Modul zu laden ,-)
Benutzeravatar
jens
Moderator
Beiträge: 8482
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Freitag 30. September 2005, 12:32

Zu früh gefreut, denn ".im_func.func_code.co_varnames" liefert nämlich nicht nur die argumente der Methode, sondern zusätzlich alle Variablen, die es in der Methode gibt:

Code: Alles auswählen

class test:
    def test1(self, arg1, arg2):
        ich_auch = 123
        print arg1, arg2
        und_auch_ich = "blabla"

print test().test1.im_func.func_code.co_varnames
Liefert:

Code: Alles auswählen

('self', 'arg1', 'arg2', 'ich_auch', 'und_auch_ich')
In meinem Fall brauche ich aber wirklich nur die argumente im "Methodenkopf" (also 'arg1', 'arg2') :(
Zuletzt geändert von jens am Samstag 1. Oktober 2005, 20:57, insgesamt 1-mal geändert.

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Freitag 30. September 2005, 12:42

Ich würde eher das Modul inspect verwenden, statt auf irgendwelche schlecht dokumentierten Sachen zuzugreifen - vielleicht will es noch jemand enderes lesen und bei inspect sieht man halt sofort was ich mir dabei gedacht hatte.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Benutzeravatar
jens
Moderator
Beiträge: 8482
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Freitag 30. September 2005, 12:50

Hast recht, was die Doku angeht. Ich hab nur das gefunden:
http://www.python.org/doc/current/ref/types.html#l2h-87

Aber ist es ein Grund die eingebaute Funktion nicht zu benutzten? Ich denke es ist ehr ein ansporn die Doku mal aufzumöbeln... Aber das ist wieder ein anderes Thema :?

Ich sehe einfach den Vorteil darin, inspect nicht importieren zu müßen :)

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
jens
Moderator
Beiträge: 8482
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Samstag 1. Oktober 2005, 20:59

Zu früh gefreut, denn ".im_func.func_code.co_varnames" liefert nämlich nicht nur die argumente der Methode, sondern zusätzlich alle Variablen, die es in der Methode gibt:

Code: Alles auswählen

class test:
    def test1(self, arg1, arg2):
        ich_auch = 123
        print arg1, arg2
        und_auch_ich = "blabla"

print test().test1.im_func.func_code.co_varnames
Liefert:

Code: Alles auswählen

('self', 'arg1', 'arg2', 'ich_auch', 'und_auch_ich')
EDIT: Wobei .im_func.func_code.co_argcount hilft mir auch schon weiter... Ich geh nun hin und fange den TypeError ab um selber eine Fehlermeldung zu generieren, die z.B. so aussieht:
ModuleManager >get_CGI_data<-error: save_internal_page() takes exactly 5 arguments ['content', 'markup', 'name', 'description'], but 3 given from CGI data: ['content', 'markup', 'description'] Compare the html form and the module manager get_CGI_data config!

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
jens
Moderator
Beiträge: 8482
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Sonntag 2. Oktober 2005, 11:39

Doch noch eine Lösung gefunden. Ich hoffe nur, das die argumente im Methodenkopf immer zu erst kommen:

Code: Alles auswählen

class test:
    def test1(self, arg1, arg2):
        ich_auch = 123
        print arg1, arg2
        und_auch_ich = "blabla"

argcount = test().test1.im_func.func_code.co_argcount
varnames = test().test1.im_func.func_code.co_varnames
print varnames[1:argcount]
Ausgabe:
('arg1', 'arg2')

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
BlackJack

Sonntag 2. Oktober 2005, 22:58

Ich verstehe immer noch nicht warum Du Dich auf Deine Hoffnung verlässt statt einfach das `inspect` Modul zu benutzen. Dafür ist es schliesslich da.
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Montag 3. Oktober 2005, 10:44

BlackJack hat geschrieben:Ich verstehe immer noch nicht warum Du Dich auf Deine Hoffnung verlässt statt einfach das `inspect` Modul zu benutzen. Dafür ist es schliesslich da.
jens hat geschrieben:Ich sehe einfach den Vorteil darin, inspect nicht importieren zu müßen :)
Wobei ich zugeben muss, dass ich, genauso wie du, BlackJack, den Vorteil nicht sehe, vor allem da das Modul ja so oder so in der stdlib ist. Und es ist ja nicht so, dass ein Modul hin oder her wahnsinnige Performanceunterschiede macht.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Benutzeravatar
jens
Moderator
Beiträge: 8482
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Dienstag 4. Oktober 2005, 06:33

BlackJack hat geschrieben:Ich verstehe immer noch nicht warum Du Dich auf Deine Hoffnung verlässt statt einfach das `inspect` Modul zu benutzen. Dafür ist es schliesslich da.
Naja, deine Begründung 'Dafür ist es schliesslich da.' ist nicht gerade überzeugend ;)
Aber gut, mir fällt ein, das ich das ganze ja nur dann brauche, wenn ein Fehler aufgetreten ist, daher importiere ich inspect dann auch nur im Fehlerfall, somit ist meine Begründung auch wiederlegt. ;)

Aber machen wir es mal so:

Code: Alles auswählen

class test:
    def test1(self, arg1, arg2):
        ich_auch = 123
        print arg1, arg2
        und_auch_ich = "blabla"

import inspect
args = inspect.getargspec(test().test1)
print args
print args[0][1:]
(['self', 'arg1', 'arg2'], None, None, None)
['arg1', 'arg2']
Darf ich denn hier hoffen, das args[0][1:] immer richtig ist?

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
BlackJack

Mittwoch 5. Oktober 2005, 00:36

jens hat geschrieben:
BlackJack hat geschrieben:Ich verstehe immer noch nicht warum Du Dich auf Deine Hoffnung verlässt statt einfach das `inspect` Modul zu benutzen. Dafür ist es schliesslich da.
Naja, deine Begründung 'Dafür ist es schliesslich da.' ist nicht gerade überzeugend ;)
Nicht? Du verlässt Dich also lieber auf selbstgeschriebenen Quelltext, der ziemlich tief in den "Eingeweiden" der Sprache rumwühlt, anstatt ein Modul aus der Standardbibliothek zu benutzen, welches gut getestet ist, auch in der nächsten Python Version noch funktioniert und eigentlich auch in Jython, IronPython und PyPy vorhanden sein sollte. Auch wenn dort die Interna von Funktionen und Methoden ganz anders aussehen könnten und Dein Code da auf die Nase fallen könnte!? :twisted:
Benutzeravatar
jens
Moderator
Beiträge: 8482
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Mittwoch 5. Oktober 2005, 06:49

Die Begründung hört sich schon viel besser an. Ich verwende auch inspect... Aber...
Ich hab mir jetzt mal inspect.getargspec() angesehen. Es benutzt auch im_func, co_argcount und co_varnames. Das ganze bietet zwar noch mehr informationen, aber die brauche ich garnicht...

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
BlackJack

Mittwoch 5. Oktober 2005, 23:58

jens hat geschrieben:Die Begründung hört sich schon viel besser an. Ich verwende auch inspect... Aber...
Ich hab mir jetzt mal inspect.getargspec() angesehen. Es benutzt auch im_func, co_argcount und co_varnames. Das ganze bietet zwar noch mehr informationen, aber die brauche ich garnicht...
Das die Funktion in CPython `im_func` usw. benutzt ist ein Implementierungsdetail. Wenn man das in Jython benutzt, könnte ich mir zum Beispiel vorstellen, das die Java Reflection API stattdessen benutzt wird. Der Vorteil: Du brauchst Dich um solche "Kleinigkeiten" nicht kümmern.
Antworten