OPERATORS = {'+': (1, lambda x, y: x + y), '-': (1, lambda x, y: x - y), '*': (2, lambda x, y: x * y), '/': (2, lambda x, y: x / y)} eval_ , to the input of which a string with a calculated expression is supplied: def eval_(formula_string):   def parse(formula_string): number = '' for s in formula_string: if s in '1234567890.': #   - ,    number += s elif number: #    ,         yield float(number) number = '' if s in OPERATORS or s in "()": #   -   ,     yield s if number: #      ,   yield float(number)   def shunting_yard(parsed_formula): stack = [] #      for token in parsed_formula: #   - ,       , #      , #      . #    ,    - if token in OPERATORS: while stack and stack[-1] != "(" and OPERATORS[token][0] <= OPERATORS[stack[-1]][0]: yield stack.pop() stack.append(token) elif token == ")": #   -  ,     ,   , #      . while stack: x = stack.pop() if x == "(": break yield x elif token == "(": #   -  ,      stack.append(token) else: #   - ,      yield token while stack: yield stack.pop()   def calc(polish): stack = [] for token in polish: if token in OPERATORS: #    - , y, x = stack.pop(), stack.pop() #  2    stack.append(OPERATORS[token][1](x, y)) #  ,    else: stack.append(token) return stack[0] #   -       return calc(shunting_yard(parse(formula_string)))  %timeit eval("2+2") 100000 loops, best of 3: 12.8 µs per loop %timeit eval_("2+2") 100000 loops, best of 3: 7.61 µs per loop  %timeit eval("15/(7-(1+1))*3-(2+(1+1))") 10000 loops, best of 3: 29.7 µs per loop %timeit eval_("15/(7-(1+1))*3-(2+(1+1))") 10000 loops, best of 3: 36.3 µs per loop  %timeit eval("15/(7-(1+1))*3-(2+(1+1))*15/(7-(1+1))*3-(2+(1+1))*(15/(7-(1+1))*3-(2+(1+1))+15/(7-(1+1))*3-(2+(1+1)))") 10000 loops, best of 3: 86.3 µs per loop %timeit eval_("15/(7-(1+1))*3-(2+(1+1))*15/(7-(1+1))*3-(2+(1+1))*(15/(7-(1+1))*3-(2+(1+1))+15/(7-(1+1))*3-(2+(1+1)))") 10000 loops, best of 3: 147 µs per loop  OPERATORS = {'+': (1, lambda x, y: x + y), '-': (1, lambda x, y: x - y), '*': (2, lambda x, y: x * y), '/': (2, lambda x, y: x / y)} def eval_(formula): def parse(formula_string): number = '' for s in formula_string: if s in '1234567890.': number += s elif number: yield float(number) number = '' if s in OPERATORS or s in "()": yield s if number: yield float(number) def shunting_yard(parsed_formula): stack = [] for token in parsed_formula: if token in OPERATORS: while stack and stack[-1] != "(" and OPERATORS[token][0] <= OPERATORS[stack[-1]][0]: yield stack.pop() stack.append(token) elif token == ")": while stack: x = stack.pop() if x == "(": break yield x elif token == "(": stack.append(token) else: yield token while stack: yield stack.pop() def calc(polish): stack = [] for token in polish: if token in OPERATORS: y, x = stack.pop(), stack.pop() stack.append(OPERATORS[token][1](x, y)) else: stack.append(token) return stack[0] return calc(shunting_yard(parse(formula))) Source: https://habr.com/ru/post/273253/
All Articles