Katakanlah saya memiliki contoh yang agak dibuat-buat seperti:

X = {'a':True, 'b':False}
x = ("a","and","b")
y = ("a","or","b")

def func(z):
    return X[z[0]] 'and/or' X[z[2]]

Apakah ada cara cepat untuk membangun logika seperti itu:

  1. tanpa eval, karena ini adalah overhead yang signifikan untuk fungsi yang dievaluasi dalam satu lingkaran ~1e6 kali
  2. tanpa logika if/else karena lagi-lagi akan menambah overhead dan logika nyata bisa panjang?
1
Sergey Bushmanov 12 Mei 2021, 18:57

2 jawaban

Jawaban Terbaik

Anda dapat menggunakan operator dengan rekursi untuk menangani string ekspresi arbitrer:

import operator
X = {'a':True, 'b':False}
def _eval(s):
   l, o = None, None
   while (n:=next(s, None)) not in {')', None}:
      if n in {'and', 'or'}:
         o = n
      else:
         v = n if n != '(' else _eval(s)
         if l is None:
            l = v
         else:
            s = iter([getattr(operator, f'{o}_')(X.get(l, l), X.get(v, v)), *s])
            l, o = None, None
   return l

import re
def run_eval(s):
   return _eval(iter(re.findall('\(|\)|\w+', s)))

print(run_eval('a and b'))
print(run_eval('a or b'))
print(run_eval('a and (b or (a and b)) or b'))

Keluaran:

False
True
False

Sunting: mengevaluasi input berbasis Tuple:

from collections import deque
X = {'a':True, 'b':False, 'c':True}
def _eval(t):
   d = deque(t) #using deque for faster element removal and addition
   while len(d) > 1:
      a, b, c = [d.popleft() for _ in range(3)]
      v1, v2 = X[a] if a in X else (a if not isinstance(a, tuple) else _eval(a)), X[c] if c in X else (c if not isinstance(c, tuple) else _eval(c))
      d.appendleft(getattr(operator, f'{b}_')(v1, v2))
   return d[0]

def run_eval(t):
   return _eval(t)

print(run_eval(("a", "and","b")))
print(run_eval(("a", "or","b", "or", "c")))
print(run_eval((("a","and","b"), "or",("a","and","b"))))

Keluaran:

False
True
False
3
Ajax1234 12 Mei 2021, 17:10