10 Stimmen

Python: Übergabe von Flags an Funktionen

Für eine lange Zeit habe ich versucht, herauszufinden, was ist der beste Weg, um Flags an Python-Funktionen übergeben. Der einfachste Weg ist etwas wie:

def func(data, flag1, flag2, flag3):
    ...

func(my_data, True, False, True)

Das ist wirklich schön und prägnant, aber unglaublich schwer zu lesen, da das Wort "True" oder "False" nichts darüber aussagt, welches Flag gesetzt wird, und man die Argumente sorgfältig von links nach rechts zählen muss. Man kann sie zu Schlüsselwortargumenten machen:

def func(data, flag1=False, flag2=False, flag3=False):
    ...

func(my_data, flag1=True, flag3=True)

aber das ist irgendwie überflüssig, da das "True" überhaupt keine Bedeutung hat. Ich könnte es als Liste übergeben:

func(mydata, ['flag1', 'flag3'])

または

func(mydata, [func.flag1, func.flag3])

Aber das erste fühlt sich ziemlich schmutzig an, da es Zeichenketten als Flaggen verwendet, und das zweite ist immer noch etwas repetitiv. Im Idealfall möchte ich etwas sagen wie:

func(my_data, flag1, flag3)

um Flags an eine Funktion mit minimaler Ausführlichkeit und Redundanz zu übergeben. Gibt es eine Möglichkeit, etwas wie dies in Python zu tun?

EDIT: Ich entschied mich für:

func(mydata, flagA=1, flagB=1)

vor allem aus den genannten Gründen: Überprüfung bei der Kompilierung (im Gegensatz zur Übergabe von Zeichenketten), keine Verschmutzung des Namensraums (im Gegensatz zur Verwendung globaler "ENUM "s) und minimaler Ballast (=1 oder =0 besteht aus nur 2 Zeichen, im Gegensatz zu 5 oder 6 für =True oder =False). Es macht auch das Setzen von Standardwerten für die Flags sehr einfach:

def func(data, flagA=1, flagB=0, flagC=1):
    ...

was weitaus übersichtlicher und einfacher ist, als durch Reifen zu springen, um Standardwerte zu extrahieren und **kwarg-ähnlichen Flags zuzuweisen. Die Flags werden grundsätzlich statisch geprüft und sind sehr klar und sauber zu schreiben. Wenn ich jetzt nur noch die letzten beiden Zeichen abschneiden könnte...

5voto

Jakub M. Punkte 29835

Können Sie definieren flag1 ... flagN als globale Variablen, und definieren Sie Ihre Funktion mit func( *args)

FLAG1 = 1
FLAG2 = 2

def func(*args):
   pass

func(FLAG1, FLAG2)

Indem Sie die Flags separat definieren, anstatt einen String zu verwenden, können Sie Tippfehler in den Namen der Flags und einige Kopfschmerzen beim Debuggen vermeiden

5voto

RickyA Punkte 14540

Ich vermisse die gute alte bitweise Flaggen:

a = 1
b = 2
c = 4
d = 8

def func( data, flags ):
    print( ( flags & a) == a )
    print( ( flags & b) == b )
    print( ( flags & c) == c )
    print( ( flags & d) == d )

>>>> func("bla", a|c|d)
>>>> True
>>>> False
>>>> True
>>>> True

4voto

hamstergene Punkte 23394

Einige Python-Standardbibliotheken verwenden dies:

re.match(pattern, str, re.MULTILINE | re.IGNORECASE)

Sie können diesen Ansatz durch die Verwendung von *args abwandeln:

my.func(a, b, c, my.MULTLINE, my.IGNORECASE)

Ich würde wirklich empfehlen, mit flag1=True zu arbeiten:

  • es ist lesbar
  • der Name des Flags wird bei der Kompilierung geprüft (es sei denn, **kwargs wird verwendet)
  • Sie können flag=1 und flag=0 anstelle von True und False verwenden, um das Rauschen zu reduzieren.
  • Sie können LONG_FLAG_NAME_YOU_DONT_REMEMBER=True vorübergehend in False ändern, ohne den langen Namen erneut einzugeben, wenn Sie ihn wieder ändern müssen

3voto

Vincent Savard Punkte 33059

Mit *args:

def some_func(data, *args):
    # do something
    return args # this is just to show how it works

>>> print some_func(12, 'test', 'test2', 'test3')
('test', 'test2', 'test3')

Dies ist eine gute Frage, um zu verstehen, wie *args und **kwargs funktionieren: *args und **kwargs?

3voto

6502 Punkte 108136

Wie wäre es, sie umzudrehen?

flag1, flag2, flag3, flag4, flag5, flag6 = range(6)

def func(enable=[], disable=[],
         enabled_by_default=[flag5, flag6]):
    enabled = set(enabled_by_default + enabled) - set(disabled)
    if flag1 in enabled:
        ...
    if flag2 in enabled:
        ...

func(enable = [flag1, flag2, flag3],
     disable = [flag6])

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X