Referenz auf die aktuelle Funktion

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
filchos
User
Beiträge: 35
Registriert: Dienstag 2. Juni 2009, 10:48
Wohnort: München
Kontaktdaten:

Hallo,

folgendes Szenario:

Ein Decorator fügt Informationen zu einer Funktion hinzu:

Code: Alles auswählen

def internal(function):
    function.internal = True
    return function
Gibt es eine einfache Möglichkeit, innerhalb der Funkion das Attribut internal auszulesen, ohne den Funktionsnamen selbst zu benutzen?

Also statt

Code: Alles auswählen

@internal
def example():
    internal = getattr(example, 'internal')
    # do something 
lieber so eine Art

Code: Alles auswählen

@internal
def example():
    internal = getattr(__THIS_IS_A_REFERENCE_TO_THE_CURRENT_FUNCTION__, 'internal')
    # do something 
?

Schöne Grüße,
Olaf
BlackJack

@filchos: Nein, gibt's nicht.
Benutzeravatar
filchos
User
Beiträge: 35
Registriert: Dienstag 2. Juni 2009, 10:48
Wohnort: München
Kontaktdaten:

Hallo BlackJack,

danke für die Antwort, dann muss ich auch nicht weitersuchen.

Grüße,
Olaf
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Dies ist ein Hack, der nur mit CPython und globalen Funktionen funktioniert...

Code: Alles auswählen

def internalize(f): f.internal = True; return f

def am_i_internal():
    import sys; f = sys._getframe(1)
    return getattr(f.f_globals[f.f_code.co_name], 'internal', False)

def foo(): 
    if am_i_internal():
        return 42
    return 2

print foo()
print internalize(foo)()
Sauber ist IMHO der Einsatz von dynamischen aka fluid Variablen:

Code: Alles auswählen

from threading import local
current = local()

def internalize(f): 
    def inner(*args, **kwargs):
        oldf = getattr(current, "f", None); current.f = f
        try:
            return f(*args, **kwargs)
        finally:
            current.f = oldf
    f.internal = True
    return inner

def am_i_internal():
    return getattr(getattr(current, "f", None), 'internal', False)

def foo(): 
    if am_i_internal():
        return 42
    return 2

print foo()
print internalize(foo)()
Stefan
Benutzeravatar
filchos
User
Beiträge: 35
Registriert: Dienstag 2. Juni 2009, 10:48
Wohnort: München
Kontaktdaten:

Hallo Stefan,

danke für Deine Antwort. Sie ist für mich allerdings hauptsächlich zum Lernen interessant. Für eine Umsetzung, für die ich auch andere Möglichkeiten habe, ist sie mir zu komplex.

Grüße,
Olaf
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

Hab ich vor kurzem mal für python-ideas geschrieben:

Code: Alles auswählen

def selffunc(func):
    @wraps(func)
    def newfunc(*args, **kwds):
        return func(func, *args, **kwds)
    return newfunc

@selffunc
def foo(func, a):
    func.cache = a
Dann lieber noch Vim 7 als Windows 7.

http://pythonic.pocoo.org/
Benutzeravatar
filchos
User
Beiträge: 35
Registriert: Dienstag 2. Juni 2009, 10:48
Wohnort: München
Kontaktdaten:

Hallo birkenfeld,

was macht die Funktion „wraps“?

Grüße,
Olaf
Benutzeravatar
Trundle
User
Beiträge: 591
Registriert: Dienstag 3. Juli 2007, 16:45

Die kommt aus dem [mod]functools[/mod]-Modul und setzt bei `newfunc` Attribute wie `__name__`, `__module__` und `__doc__`, damit `newfunc` eben so aussieht wie `func`.
"Der Dumme erwartet viel. Der Denkende sagt wenig." ("Herr Keuner" -- Bertolt Brecht)
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

Tatsächlich, da hab ich den Import vergessen.
Dann lieber noch Vim 7 als Windows 7.

http://pythonic.pocoo.org/
Antworten