2017-09-11 6 views
1

배경 : 현재 ipython을위한 라인 매직을 만들고 있습니다. 이 마술은 함수의 반환 값이 변수에 할당되는 행에만 적용됩니다.파이썬에서 라인이 유효한 함수 호출인지 어떻게 확인합니까?

필자는 파이썬에서 유효한 함수 호출 + 할당임을 확인하는 방법을 찾고있다.

예컨대

a = b() 
a,b = c(d,e="f") 
a = b(c()+c) 

하고 다음 거부되어야한다 : 다음 허용되어야한다 라인이 전혀 유효 파이썬 없다

a = def fun() # no function call 
b(a=2) # no assignment 
a = b + C# no function call 
a = b() + c() # top-level on right-hand-side must be function call 

경우이 될 수있는 바와 같이, 나는 그것이 통과 여부를 걱정하지 않는다 다른 단계에서 처리됩니다.

+0

당신은 파서를 작성해야한다. 정규식은 이것을 위해 충분히 강력하지 않습니다. –

답변

6

ast 모듈을 통해 액세스 할 수있는 파이썬의 자체 파서를 사용하여 각 문장을 직접 검사하여 오른쪽이 호출 인 과제인지 확인할 수 있습니다.

import ast 

def is_call_assignment(line): 
    try: 
     node = ast.parse(line) 
    except SyntaxError: 
     return False 
    if not isinstance(node, ast.Module): 
     return False 
    if len(node.body) != 1 or not isinstance(node.body[0], ast.Assign): 
     return False 
    statement = node.body[0] 
    return isinstance(statement.value, ast.Call) 


test_cases = [ 
    'a = b()', 
    'a,b = c(d,e="f")', 
    'a = b(c()+c)', 
    'a = def fun()', 
    'b(a=2)', 
    'a = b + c', 
    'a = b() + c()' 
] 

for line in test_cases: 
    print(line) 
    print(is_call_assignment(line)) 
    print("") 

결과 :

a = b() 
True 

a,b = c(d,e="f") 
True 

a = b(c()+c) 
True 

a = def fun() 
False 

b(a=2) 
False 

a = b + c 
False 

a = b() + c() 
False 
+0

이것은 최고입니다. 나는 당신이 그것을 할 수 있다는 것을 결코 알지 못했다! – wotanii

-1

나는이 함께 온 최고 :

  1. 가 "="
  2. 확실 브래킷 균형을 만들지 만, 브래킷 카운트 히트 경우 실패 처음이 정규 표현식을
    [A-z, ]*= *[A-z_]* *\(.*\)
  3. 분할을 적용 ,

이 3 단계가 필요한 마지막 브라켓를 실시하기 전에 0이 사건을 만들기 위해 실패 :

a = b() + c() # top-level on right-hand-side must be function call 

도 3 좀 같이 표시됩니다 단계 :

def matched(str): 
    count = 0 
    for i in str.strip(): 
     if i == "(": 
      count += 1 
     elif i == ")": 
      count -= 1 
     if count < 0 or (count < 1 and i>=len(str)-1): 
      return False 
    return count == 0 

내가 잘 실패하는 방법을 알아낼 수 없기 때문에

이 솔루션은, 끔찍하게 못생긴 (this 기준)의 경우 최상위 수준 함수 호출이 아닙니다.

훨씬 더 나은 해결책은 파이썬의 AST를 사용할 수 있지만 액세스하는 방법을 모르겠습니다.

+0

['[Az]'는 사용하지 말고'[A-Za-z]'를 사용하십시오.] (https://stackoverflow.com/questions/29771901/why-is-this-regex-allowing-a-caret/ 29771926 # 29771926) –