использование ast преобразует код в оператор в python [duplicate]

Перейти к: Настройки Android Studio> Внешний вид и amp; Поведение> Системные настройки> Android SDK:

Если путь для SDK является красным цветом, перейдите в папку SDK и нажмите ***APPLY***

4
задан Wang 22 July 2010 в 21:25
поделиться

3 ответа

Следующее работает с Python 2 или 3 и работает быстрее, чем с помощью itertools:

EDIT: WARNING:

По-видимому, этот код может висеть в некоторых (странных) ситуациях. В результате я не могу это рекомендовать.

def compare_ast(node1, node2):

    if type(node1) != type(node2):
        return False
    elif isinstance(node1, ast.AST):
        for kind, var in vars(node1).items():
            if kind not in ('lineno', 'col_offset', 'ctx'):
                var2 = vars(node2).get(kind)
                if not compare_ast(var, var2):
                    return False
        return True
    elif isinstance(node1, list):
        if len(node1) != len(node2):
            return False
        for i in range(len(node1)):
            if not compare_ast(node1[i], node2[i]):
                return False
        return True
    else:
        return node1 == node2
2
ответ дан Edward K. Ream 18 August 2018 в 10:36
поделиться

В Python идентификатор объекта сравнивается с помощью оператора is (который, в отличие от ==, не может быть перегружен). Если не реализовано идиотом, == не будет сравнивать идентичность, а скорее равенство (если это возможно и реализуется, конечно). И в случае встроенного строкового класса это, конечно, не так.

Однако может быть другая проблема с вашей реализацией: поскольку дамп создает очень точную информацию (подходящую для отладки), два asts например, переменную, названную по-разному, можно считать !=. Это может быть или не быть тем, что вы хотите.

1
ответ дан user 18 August 2018 в 10:36
поделиться
  • 1
    Такого рода точность на самом деле то, что я хочу, так как я работаю на языке, специфичном для домена, интерпретатор которого переписывает его на стандартный питон. – Wang 22 July 2010 в 21:27

Я столкнулся с той же проблемой. Я попытался пойти следующим образом: сначала опустил АСТ на некоторое упрощенное представление (дерево dicts):

def simplify(node):
    if isinstance(node, ast.AST):
        res = vars(node).copy()
        for k in 'lineno', 'col_offset', 'ctx':
            res.pop(k, None)
        for k, v in res.iteritems():
            res[k] = simplify(v)
        res['__type__'] = type(node).__name__
        return res
    elif isinstance(node, list):
        return map(simplify, node)
    else:
        return node

, а затем вы можете просто сравнить эти представления:

data = open("/usr/lib/python2.7/ast.py").read()
a1 = ast.parse(data)
a2 = ast.parse(data)
print simplify(a1) == simplify(a2)

даст вам True

EDIT

Просто понял, что нет необходимости создавать dict, поэтому вы можете сделать это только:

def compare_ast(node1, node2):
    if type(node1) is not type(node2):
        return False
    if isinstance(node1, ast.AST):
        for k, v in vars(node1).iteritems():
            if k in ('lineno', 'col_offset', 'ctx'):
                continue
            if not compare_ast(v, getattr(node2, k)):
                return False
        return True
    elif isinstance(node1, list):
        return all(itertools.starmap(compare_ast, itertools.izip(node1, node2)))
    else:
        return node1 == node2
3
ответ дан Yorik.sar 18 August 2018 в 10:36
поделиться
  • 1
    Я бы, наверное, сбросил itertools и starmap и просто проверил all(compare_ast(n1, n2) for n1, n2 in zip(node1, node2)). Кроме того, необходимо проверить длину, так как zip и izip просто счастливо завершают работу без дополнительного уведомления, когда один из итераторов короче другого. – Michael 21 March 2018 в 18:51
Другие вопросы по тегам:

Похожие вопросы: