복붙노트

[PYTHON] 파이썬에서 간단한 부울 논리를 동적으로 평가하기

PYTHON

파이썬에서 간단한 부울 논리를 동적으로 평가하기

다음과 같이 동적으로 생성 된 부울 논리 표현식이 있습니다.

자리 표시자는 부울로 바뀝니다. 해야합니까?

제안을 환영합니다.

해결법

  1. ==============================

    1.예를 들어 pyparsing을 사용하여이를 처리 할 수있는 평가기를 작성하는 것이 전혀 어렵지는 않습니다. 처리 할 연산이 몇 개 밖에 없으므로 (및 또는 그룹화?), 직접 구문 분석하고 평가할 수 있어야합니다.

    예를 들어 pyparsing을 사용하여이를 처리 할 수있는 평가기를 작성하는 것이 전혀 어렵지는 않습니다. 처리 할 연산이 몇 개 밖에 없으므로 (및 또는 그룹화?), 직접 구문 분석하고 평가할 수 있어야합니다.

    표현식을 평가하기 위해 명시 적으로 이진 트리를 형성 할 필요는 없습니다.

  2. ==============================

    2.다음은 약 1 시간 반 (리팩토링에 거의 1 시간 정도)으로 작성된 작은 모듈 (공백을 포함하여 74 줄)입니다.

    다음은 약 1 시간 반 (리팩토링에 거의 1 시간 정도)으로 작성된 작은 모듈 (공백을 포함하여 74 줄)입니다.

    str_to_token = {'True':True,
                    'False':False,
                    'and':lambda left, right: left and right,
                    'or':lambda left, right: left or right,
                    '(':'(',
                    ')':')'}
    
    empty_res = True
    
    
    def create_token_lst(s, str_to_token=str_to_token):
        """create token list:
        'True or False' -> [True, lambda..., False]"""
        s = s.replace('(', ' ( ')
        s = s.replace(')', ' ) ')
    
        return [str_to_token[it] for it in s.split()]
    
    
    def find(lst, what, start=0):
        return [i for i,it in enumerate(lst) if it == what and i >= start]
    
    
    def parens(token_lst):
        """returns:
            (bool)parens_exist, left_paren_pos, right_paren_pos
        """
        left_lst = find(token_lst, '(')
    
        if not left_lst:
            return False, -1, -1
    
        left = left_lst[-1]
    
        #can not occur earlier, hence there are args and op.
        right = find(token_lst, ')', left + 4)[0]
    
        return True, left, right
    
    
    def bool_eval(token_lst):
        """token_lst has length 3 and format: [left_arg, operator, right_arg]
        operator(left_arg, right_arg) is returned"""
        return token_lst[1](token_lst[0], token_lst[2])
    
    
    def formatted_bool_eval(token_lst, empty_res=empty_res):
        """eval a formatted (i.e. of the form 'ToFa(ToF)') string"""
        if not token_lst:
            return empty_res
    
        if len(token_lst) == 1:
            return token_lst[0]
    
        has_parens, l_paren, r_paren = parens(token_lst)
    
        if not has_parens:
            return bool_eval(token_lst)
    
        token_lst[l_paren:r_paren + 1] = [bool_eval(token_lst[l_paren+1:r_paren])]
    
        return formatted_bool_eval(token_lst, bool_eval)
    
    
    def nested_bool_eval(s):
        """The actual 'eval' routine,
        if 's' is empty, 'True' is returned,
        otherwise 's' is evaluated according to parentheses nesting.
        The format assumed:
            [1] 'LEFT OPERATOR RIGHT',
            where LEFT and RIGHT are either:
                    True or False or '(' [1] ')' (subexpression in parentheses)
        """
        return formatted_bool_eval(create_token_lst(s))
    

    간단한 테스트 결과는 다음과 같습니다.

    >>> print nested_bool_eval('')
    True
    >>> print nested_bool_eval('False')
    False
    >>> print nested_bool_eval('True or False')
    True
    >>> print nested_bool_eval('True and False')
    False
    >>> print nested_bool_eval('(True or False) and (True or False)')
    True
    >>> print nested_bool_eval('(True or False) and (True and False)')
    False
    >>> print nested_bool_eval('(True or False) or (True and False)')
    True
    >>> print nested_bool_eval('(True and False) or (True and False)')
    False
    >>> print nested_bool_eval('(True and False) or (True and (True or False))')
    True
    

    [부분적으로 화제가 될 가능성이 있음]

    token_to_char = token_to_char와 friends가 제공하는 poor-mans 의존성 주입 수단과 함께 사용하는 토큰 (피연산자와 연산자 모두)을 동시에 여러 개의 다른 평가자를 가질 수 있도록 쉽게 구성 할 수 있습니다 ( "주입 - 기본적으로 "전역"은 단일 동작으로 남겨 둡니다).

    예 :

    def fuzzy_bool_eval(s):
        """as normal, but:
        - an argument 'Maybe' may be :)) present
        - algebra is:
        [one of 'True', 'False', 'Maybe'] [one of 'or', 'and'] 'Maybe' -> 'Maybe'
        """
        Maybe = 'Maybe' # just an object with nice __str__
    
        def or_op(left, right):
            return (Maybe if Maybe in [left, right] else (left or right))
    
        def and_op(left, right):
            args = [left, right]
    
            if Maybe in args:
                if True in args:
                    return Maybe # Maybe and True -> Maybe
                else:
                    return False # Maybe and False -> False
    
            return left and right
    
        str_to_token = {'True':True,
                        'False':False,
                        'Maybe':Maybe,
                        'and':and_op,
                        'or':or_op,
                        '(':'(',
                        ')':')'}
    
        token_lst = create_token_lst(s, str_to_token=str_to_token)
    
        return formatted_bool_eval(token_lst)
    

    제공 :

    >>> print fuzzy_bool_eval('')
    True
    >>> print fuzzy_bool_eval('Maybe')
    Maybe
    >>> print fuzzy_bool_eval('True or False')
    True
    >>> print fuzzy_bool_eval('True or Maybe')
    Maybe
    >>> print fuzzy_bool_eval('False or (False and Maybe)')
    False
    
  3. ==============================

    3.관심이있는 지역 및 전역 변수로 딕테이션을 설정하면 eval ()에 표현식과 함께 전달할 수 있어야합니다.

    관심이있는 지역 및 전역 변수로 딕테이션을 설정하면 eval ()에 표현식과 함께 전달할 수 있어야합니다.

  4. ==============================

    4.SymPy 로직 모듈을 사용하는 케이크 조각처럼 들립니다. 그들은 심지어 그 문서의 예를 가지고 있습니다 : http://docs.sympy.org/0.7.1/modules/logic.html

    SymPy 로직 모듈을 사용하는 케이크 조각처럼 들립니다. 그들은 심지어 그 문서의 예를 가지고 있습니다 : http://docs.sympy.org/0.7.1/modules/logic.html

  5. from https://stackoverflow.com/questions/2467590/dynamically-evaluating-simple-boolean-logic-in-python by cc-by-sa and MIT license