Seite 1 von 1

Referenz auf die aktuelle Funktion

Verfasst: Dienstag 2. Juni 2009, 10:55
von filchos
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

Verfasst: Dienstag 2. Juni 2009, 11:04
von BlackJack
@filchos: Nein, gibt's nicht.

Verfasst: Dienstag 2. Juni 2009, 11:05
von filchos
Hallo BlackJack,

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

Grüße,
Olaf

Verfasst: Dienstag 2. Juni 2009, 11:31
von sma
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

Verfasst: Dienstag 2. Juni 2009, 18:07
von filchos
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

Verfasst: Dienstag 2. Juni 2009, 18:59
von birkenfeld
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

Verfasst: Mittwoch 3. Juni 2009, 06:56
von filchos
Hallo birkenfeld,

was macht die Funktion „wraps“?

Grüße,
Olaf

Verfasst: Mittwoch 3. Juni 2009, 07:00
von Trundle
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`.

Verfasst: Mittwoch 3. Juni 2009, 08:04
von birkenfeld
Tatsächlich, da hab ich den Import vergessen.