Seite 1 von 1

Wie Assignments in if-Statements ersetzen

Verfasst: Mittwoch 13. Mai 2009, 20:59
von webster
Hallo,
aus C und Perl bin ich Ausdrücke der Art

Code: Alles auswählen

if (foo = function()) ...
gewöhnt. Konkret hätte ich das gerne für folgenden Anwendungsfall:

Code: Alles auswählen

if match = pattern1.match(line):
    block1
elif match = pattern2.match(line):
    block2
elif match = pattern3.match(line):
    block3
else:
    block4
Nach dem ganzen If-then-else soll das letzte match-Objekt erhalten bleiben, also darf ich nicht einfach weitermatchen, wenn ich schon was gefunden habe.
Als Anfänger sehe ich bisher nur zwei Möglichkeiten.
1) Eine hässliche Verschachtelung von ifs bis zur Tiefe 4.
2) Ich packe die Patterns in eine Liste und iteriere darüber. Das ist meiner Meinung nach aber Overkill für eine fixe Menge von Pattern. Das muss irgendwie einfacher gehen.

Danke schonmal.

Verfasst: Mittwoch 13. Mai 2009, 21:03
von BlackJack
Die Liste ist es. Wieso sollte das "Overkill" sein?

Verfasst: Mittwoch 13. Mai 2009, 21:34
von sma
Eine Schleife ist allgemein recht elegant:

Code: Alles auswählen

def block1(): pass
def block2(): pass
def block3(): pass
def default(): pass

matchers = [
	(re.compile("a"), block1),
	(re.compile("b"), block2),
	(re.compile("c"), block3),
]

for matcher, code in matchers:
	m = matcher.match(line)
	if m:
		code()
		break
else:
	default()
Bei genau 4 Varianten aber dann doch recht aufwendig. Wenn es machtbar ist, würde ich einfach alle 4 Pattern kombinieren und jeden zu einer Gruppe machen. Dann braucht man nur 1x match und kann dann über lastindex verzweigen:

Code: Alles auswählen

matcher = re.compile("(a)|(b)|(c)|(d)")

m = matcher.match(line)
if m:
  if m.lastindex == 1:
    block1
  elif m.lastindex == 2:
    block2
  elif m.lastindex == 3:
    block3
  else:
    default
Für Python 3 fällt mir noch folgendes ein:

Code: Alles auswählen

def match_line(line):
  m = None
  def match(pattern): nonlocal m; m = pattern.match(line); return m
  if match(p1):
    block1
  elif match(p2):
    block2
  elif match(p3):
    block3
  else:
    default
Stefan

Verfasst: Mittwoch 13. Mai 2009, 22:12
von webster
Danke für die Antworten.
Ich habe jetzt folgendes Schema benutzt, das erscheint mir am einfachsten auch wenn es nicht schön ist:

Code: Alles auswählen

while True:
    match = pattern1.match(line)
    if match:
        block1
        break
    match = pattern2.match(line)
    if match:
        block2
        break
    match = pattern3.match(line)
    if match:
        block3
        break
    match = pattern4.match(line)
    if match:
        block4
        break

Verfasst: Mittwoch 13. Mai 2009, 22:28
von BlackJack
@webster: Da sollte dann aber wirklich besser eines der Muster passen. ;-)

Verfasst: Mittwoch 13. Mai 2009, 22:42
von webster
Kleine Einrückungen, große Wirkung :)

Code: Alles auswählen

while True:
    match = pattern1.match(line)
    if match:
        block1
        break
    match = pattern2.match(line)
    if match:
        block2
        break
    match = pattern3.match(line)
    if match:
        block3
        break
    match = pattern4.match(line)
    if match:
        block4
    break

Verfasst: Mittwoch 13. Mai 2009, 23:15
von birkenfeld
Wer sich gern an Undokumentiertes wagt, kann sich auch `re.Scanner` anschauen :)

Verfasst: Mittwoch 13. Mai 2009, 23:22
von BlackVivi
Denk ich zu leicht, wenn ich an ein dict denke? =/ Bei mir löst ein dict oft so hässliche if-Verschachtelungen!

Verfasst: Donnerstag 14. Mai 2009, 09:38
von helduel
BlackVivi hat geschrieben:Denk ich zu leicht, wenn ich an ein dict denke? =/ Bei mir löst ein dict oft so hässliche if-Verschachtelungen!
Wie sollte ein dict in diesem Fall aussehen? Ich empfinde eine Schleife hier als die eleganteste Variante. Ist auch schöner erweiterbar.