2016-09-02 2 views
0
내가 그런 짓을 할

을 실행합니다?뭔가 변수 할당

나는이에 대한 일반적인 기능 (DRY 시행) 쓰기를 시도하고있다 :

def save_form(model, formset, foreignkey_assignment, *args){ 
    for f, i in zip(formset, xrange(len(formset))): 
     cd = f.cleaned_data 
     get_key_name = lambda x: cd.get(x) 
     ast.literal_eval(foreignkey_assignment) 
     m = model(**{k:get_key_name(k) for k in args}) 
     m.save() 
} 
+0

'* args'에 들어가야하는 키 목록이 이미 있다면, 왜 'literal_eval'을 가지고 무엇인가를 지정해야합니까? – Kevin

답변

1

예 수

exec('a=1;b=2') 
:

for f, i in zip(task_set, xrange(len(task_set))): 
     cd = f.cleaned_data 
     t_name = cd.get('t_name') 
     start_date = cd.get('start_date') 
     end_date = cd.get('end_date') 
     project = Project.objects.get(pro_id=p.pro_id) 
     task = Task(t_name=t_name, start_date=start_date, 
        end_date=end_date, project=project) 
     task.save() 
     tasks_list.append(task) 

그래서 나는 다음을 쓰기 시작을

하지만 그렇게해서는 안됩니다. Why should exec() and eval() be avoided?

+0

정확하게, OP가 할당을 지원하는 ast.literal_eval()과 같은 것을 요구하고있는 이유입니다. –

2

ast.literal_eval() 평가의 AST 구문 분석 트리를 '실행'하고이를 표준 Python 리터럴 만 허용하는 엄격한 하위 집합으로 제한합니다. source code을 가져 와서 할당 지원을 추가 할 수 있습니다 (이름을 처리하기 위해 별도의 사전을 사용합니다).

당신은 AssignName 노드 처리 (파이썬 3 버전)을 추가해야 할 것 :

def literal_eval(node_or_string, namespace): 
    """ 
    Safely evaluate an expression node or a string containing a Python 
    expression. The string or node provided may only consist of the following 
    Python literal structures: strings, bytes, numbers, tuples, lists, dicts, 
    sets, booleans, and None. 
    """ 
    if isinstance(node_or_string, str): 
     node_or_string = ast.parse(node_or_string, mode='exec') 
    if isinstance(node_or_string, ast.Module): 
     node_or_string = node_or_string.body 
    def _convert(node, ns=None): 
     if isinstance(node, (ast.Str, ast.Bytes)): 
      return node.s 
     elif isinstance(node, ast.Num): 
      return node.n 
     elif isinstance(node, ast.Tuple): 
      return tuple(map(_convert, node.elts)) 
     elif isinstance(node, ast.List): 
      return list(map(_convert, node.elts)) 
     elif isinstance(node, ast.Set): 
      return set(map(_convert, node.elts)) 
     elif isinstance(node, ast.Dict): 
      return dict((_convert(k), _convert(v)) for k, v 
         in zip(node.keys, node.values)) 
     elif isinstance(node, ast.NameConstant): 
      return node.value 
     elif isinstance(node, ast.UnaryOp) and \ 
      isinstance(node.op, (ast.UAdd, ast.USub)) and \ 
      isinstance(node.operand, (ast.Num, ast.UnaryOp, ast.BinOp)): 
      operand = _convert(node.operand) 
      if isinstance(node.op, ast.UAdd): 
       return + operand 
      else: 
       return - operand 
     elif isinstance(node, ast.BinOp) and \ 
      isinstance(node.op, (ast.Add, ast.Sub)) and \ 
      isinstance(node.right, (ast.Num, ast.UnaryOp, ast.BinOp)) and \ 
      isinstance(node.left, (ast.Num, ast.UnaryOp, ast.BinOp)): 
      left = _convert(node.left) 
      right = _convert(node.right) 
      if isinstance(node.op, ast.Add): 
       return left + right 
      else: 
       return left - right 
     elif isinstance(node, ast.Assign) and \ 
      len(node.targets) == 1 and \ 
      isinstance(node.targets[0], ast.Name): 
       assert isinstance(ns, dict) # will be None when not top-level 
       ns[node.targets[0].id] = _convert(node.value) 
       return 
     raise ValueError('malformed node or string: ' + repr(node)) 
    return _convert(node_or_string, namespace) 

을 아니면 정확히 간단한 표현과 할당을 지원하고, 더 작은을 수행하는 asteval project을 사용할 수 있습니다, AST 트리 해석을 사용합니다.