Logische Verknüpfungen als Variable

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
basstscho
User
Beiträge: 2
Registriert: Mittwoch 18. September 2013, 12:57

Hallo zusammen,

ich bekomme einen Vergleichsoperator aus einer Variable und muss diesen in eine logische Verknüpfung einbauen - wie geht das?

Code: Alles auswählen

varE = 1
varA = 1
varC = 2
vo = "=="
if varE==varA and varC==varA:
    pass

#Wie kann ich das mittels dem dynamischen logischen Operator in der Variable vo realisieren?
coStr = varE + vo + varA + " and " + varC + vo + varA
if doSomeMagic(coStr):
    pass
Danke euch,
Johannes
Sirius3
User
Beiträge: 17747
Registriert: Sonntag 21. Oktober 2012, 17:20

@basstscho: Zu jedem Operator gibt es auch eine entsprechende Funktion. Diese sind im Modul »operator« zusammengefasst:

Code: Alles auswählen

import operator
varA = 1
varC = 2
vo = operator.eq
if vo(varA,varC):
    dosomething
Ich glaube aber nicht, dass das die optimale Lösung ist. Kannst Du Dein Problem noch näher beschreiben?
anogayales
User
Beiträge: 456
Registriert: Mittwoch 15. April 2009, 14:11

Hallo basstscho,

willkommen in Forum. Es gibt Wege wie du das in python realisieren kannst, sowie du es aber über Strings machst ist es sehr unüblich. Am besten sagst du uns was du eigentlich machen willst.

Falls du trotzdem das Ganze über Strings lösen willst musst du eine Abbildung konstruieren, die dir sagt welche String auf welchen Operator abbildet. So zum Beispiel:

Code: Alles auswählen

import operator

operator_mapping = {"==" : operator.eq,
			     "and" : operator.iand}

e = 1
a = 1
c = 2
vo = "=="
vi = "and"

result = operator_mapping[vi](operator_mapping[vo](c,a), operator_mapping[vo](e,a))
print result
Du siehst, dass du die Argumente nach dem Operator schreiben musst, du verlierst also die Infixnotation und nutzt stattdessen die Prefixnotation.

Den folgenden Abschnitt solltest du auf keinen Fall in produkivem Code verwenden! Er löst zwar das Problem, er dient lediglich zur Demonstration.

Code: Alles auswählen

result = eval("e {op1} a {op2} c {op1} a".format(op1="==", op2="and"))
print result
Grüße,
anogayales
Zuletzt geändert von anogayales am Mittwoch 8. Januar 2014, 10:04, insgesamt 3-mal geändert.
Benutzeravatar
bwbg
User
Beiträge: 407
Registriert: Mittwoch 23. Januar 2008, 13:35

Da Funktionen auch Objekte sind, kann man diese wunderbar in Datenstrukturen packen.

Hier bietet sich eine lookup-table an, welche Zeichenketten auf Funktionen abbildet.

Zusammen mit dem operator-Modul sähe das zum Beispiel so aus:

Code: Alles auswählen

 OPERATOR_LOOKUP = {
    '==': operator.eq,
    '+':  operator.add,
    # ...
    }
    
def main():
    a = 13
    b = 29
    print(OPERATOR_LOOKUP['=='](a, b))
    print(OPERATOR_LOOKUP['+'](a, b))
    
if __name__ == '__main__':
    main()
Edit: Zu langsam.

Wenn es sowas noch nicht gibt, sollte man eine PEP starten mit dem Ziel eval in evil umzubenennen.
"Du bist der Messias! Und ich muss es wissen, denn ich bin schon einigen gefolgt!"
BlackJack

Und vor allem sollte man Leuten die man nicht einschätzen kann nicht gleich mit der Nase drauf stossen. :?
anogayales
User
Beiträge: 456
Registriert: Mittwoch 15. April 2009, 14:11

Lieber Leute davor explizit warnen, als dass sie selbst mit der Nase drauf stoßen und es gar in produktivem Code einsetzen, weil sie es nicht besser wissen.
Sirius3
User
Beiträge: 17747
Registriert: Sonntag 21. Oktober 2012, 17:20

@anogayales: wie eine Warnung liest sich Dein Beitrag dazu aber nicht gerade.
anogayales
User
Beiträge: 456
Registriert: Mittwoch 15. April 2009, 14:11

Danke Sirius3, ich haben es nun deutlicher formuliert.
basstscho
User
Beiträge: 2
Registriert: Mittwoch 18. September 2013, 12:57

Hallo zusammen,

vielen Dank für eure zahlreichen Antworten. Nochmals kurz zum Hintergrund:
Ich habe in einer csv-Tabelle mehrere Spalten die für eine Variable stehen. In den Zeilen stehen dann jeweils Werte. Es soll nun überprüft werden welche Zeilen auf Grund des aktuellen Variablenstatus erfüllt sind und welche nicht. Zusätzlich kommt hinzu, dass in den Zellen zum Wert vorangestellt die Vergleichsoperatoren >, <, >=, <= stehen können.
Ich habe es nun mit einer Schleife gelöst die über sämtliche Werte in einer Zeile läuft und eine Unterfunktion aufruft die mit einem String-Vergleich überprüft welcher Operator zum Einsatz kommen soll (zunächst die mit zwei Zeichen, dann die mit einem und bei keinem (entsprich das ==)) und dann mittels der entsprechenden Operator-Funktion vergleicht. Bekomme ich einmal im Durchlauf ein False zurück, ist die ganze Zeile nicht erfüllt.

Somit kann ich vorab noch überprüfen ob die Eingabe Sinn macht und gehe nicht direkt aus der Benutzereingabe in den Vergleich.

Habt ihr noch ne bessere Idee?

Beste Grüße,
Johannes
Sirius3
User
Beiträge: 17747
Registriert: Sonntag 21. Oktober 2012, 17:20

@basstscho: sehe ich das richtig, die Datei sieht so aus?

Code: Alles auswählen

123,>9,<=17
4,9,>23
Wer denkt sich denn sowas aus?

Code: Alles auswählen

import csv
import operator
from itertools import imap

OPERATORS = [
    ('<=', operator.le),
    ('>=', operator.ge),
    ('<>', operator.ne),
    ('!=', operator.ne),
    ('==', operator.eq),
    ('<', operator.lt),
    ('>', operator.gt),
    ('=', operator.eq),
    ('', operator.eq),
]

def split_operator(value):
    if isinstance(value, basestring):
        for symbol, operation in OPERATORS:
            if value.startswith(symbol):
                return float(value[len(symbol):]), operation
        raise RuntimeError('Internal Error')
    else:
        return float(value), operator.eq

def validate(values):
    values = iter(values)
    first = float(next(values))
    return all(operation(first, value)
        for value, operation in imap(split_operator, values))
    
def main():
    with open('datei.csv') as data: 
        for row in csv.reader(data):
            print validate(row)
    
if __name__ == '__main__':
    main()
Antworten