Attribute innerhalb Funktion mit setattr() setzen...?

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
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

Hallo,

ich habe folgendes:

Code: Alles auswählen

def eprint(*objects, **kwargs):
    KEYWORDS = (('x', None),
                ('y', None),
                ('sep', ' '),
                ('end', ''),
                ('file', sys.stdout))
    for kw in kwargs.iterkeys():
        if not kw in [_kw[0] for _kw in KEYWORDS]:
            raise TypeError(unexp_kw.format('eprint()', kw))
    x = kwargs.get('x', None)
    y = kwargs.get('y', None)
    sep = kwargs.get('sep', ' ')
    end = kwargs.get('end', '')
    file = kwargs.get('file', sys.stdout)
#...
Nun möchte ich die 5 Zeilen, in denen ich Werte zuweise durch

Code: Alles auswählen

#...
    for kw, default in KEYWORDS:
        setattr(?object?, kw, kwargs.get(kw, default))
#...
ersetzen. Jetzt ist mir allerdings nicht klar, wie ich an 'object' komme. Wenn ich die Funktion selbst verwende, füge ich die Namen an dessen '__dict__' an, was ich ja nicht möchte. Ich brauche die Namen im Namensraum der Funktion, letztlich das, was ich in den 5 Zuweisungszeilen mache...

Habe schon mit 'inspect' experimentiert, hat mich aber auch nicht wirklich weitergebracht...

Hmm... weiß jemand Rat?

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

Wieso so kompliziert?

Code: Alles auswählen

def eprint(*objects, x=None, y=None, sep='', end='', file=sys.stdout): …
Oder verstehe ich das Problem falsch?
the more they change the more they stay the same
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

@Dav1d:
So wär's natürlich am Schönsten, geht aber leider erst ab Python 3...

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

Jain:

Code: Alles auswählen

def eprint(x=None, y=None, sep='', end='', file=sys.stdout, *objects): …
funktioniert auch mit Python 2.7

Wobei das mehr als komisch ist

Code: Alles auswählen

In [5]: def eprint(x=None, y=None, sep='', end='', file=sys.stdout, *objects): print objects

In [6]: eprint(12, 13)
()

In [7]: eprint(None, None, '', '', None, 1, 2)
(1, 2)
the more they change the more they stay the same
frabron
User
Beiträge: 306
Registriert: Dienstag 31. März 2009, 14:36

Wieso komisch? Du meinst, dass 12, 13 in *objects landen müsste? Aber Position ging doch schon immer vor Keyword-Benamsung?!
Zap
User
Beiträge: 533
Registriert: Freitag 13. Oktober 2006, 10:56

@mutella: Muss denn diese Magie der Namensraumbindung sein !?

Man muss dann natürlich eprint immer iterierbare Objects geben. Aber das ist ja nicht umbedingt ein Nachteil.

Code: Alles auswählen

def eprint(objects, x=None, y=None, sep='', end='', file=sys.stdout):
    for obj in objects:
        ...

eprint((1,2), file=sys.stderr)
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

@frabron:
Wenn ich 'objects' als 'vararg' definiere und an erster Stelle haben möchte, bleibt mir nichts weiter übrig, als dahinter ein keyword-dict zu setzen.
Andernfalls müsste ich

Code: Alles auswählen

def eprint(x=None, y=None, *objects):
    ...
machen. Und dann wäre die Parameterübergabe, wie Dav1d ja schon zeigt, in der Tat umständlich.
Zap hat geschrieben:Man muss dann natürlich eprint immer die iterierbare Objects geben. Aber das ist ja nicht umbedingt ein Nachteil.
Doch, finde ich schon:

Code: Alles auswählen

eprint(('Ein Text', 'und eine', 5), sep='...')
ist für eine 'print'-Funktion IMHO umständlicher als

Code: Alles auswählen

eprint('Ein Text', 'und eine', 5, sep='...')
Letztlich möchte ich für 'eprint()' eine Parameterübergabe wie es die 'print()'-Funktion ab Python 3 macht. Allerdings unter der eingeschränkten Python 2 Parameterübergabe...

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Zap
User
Beiträge: 533
Registriert: Freitag 13. Oktober 2006, 10:56

Als weitere Alternative könnte man darüber nachdenken eine Eprint class einzufügen.

Code: Alles auswählen

class Eprint(object):
    def __init__(self, x=None, y=None, sep='', end='', file=sys.stdout):
        ...

    def __call__(self, *objects):
        ...

# create my pre configured eprint function
eprint = Eprint(sep="\n")
eprint(1, 2, 3, "yeah")

m.E. besser als den Namensraum magisch zu verbiegen.
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

Oder du handhabst das ganze weiterhin als dict.
the more they change the more they stay the same
frabron
User
Beiträge: 306
Registriert: Dienstag 31. März 2009, 14:36

@mutetella:
Ich bezog mich auf
Dav1d hat geschrieben: [...]
Wobei das mehr als komisch ist

Code: Alles auswählen

In [5]: def eprint(x=None, y=None, sep='', end='', file=sys.stdout, *objects): print objects

In [6]: eprint(12, 13)
()

In [7]: eprint(None, None, '', '', None, 1, 2)
(1, 2)
was imo (in [6]) so funktioniert wie soll und nicht komisch ist, es sei denn hier ist die Optik gemeint, was ich aber nicht herausgelesen habe :K
Aber wenn's dir ja klar ist, dann ist ja alles gut. Manchmal stehe ich einfach auf dem Schlauch :mrgreen:
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

Ja ich meinte die Optik, natürlich muss das so funktionieren.
the more they change the more they stay the same
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

@mutella:
Meines Wissens nach gibt es keinen einfachen Weg aus Python heraus, den lokalen Namensraum programmatisch zu erweitern (wie wärs mit eval/exec :twisted:). Für den globalen Namensraum gehts über globals() oder setattr(module,...), da der als dict vorliegt, was nicht der Fall ist für den lokalen.

Warum müssen die Werte von kwargs unbedingt an einzelnen Bezeichnern lokal hängen? Einzige Fälle, die mir spontan einfallen, sind Closures/lokale Funktionen oder übergebene Funktionen, die bestimmte Bezeichner oder eine bestimmte "Umgebung" erwarten.
Antworten