Замените выражение, содержащее '/', вызовом функции div в Python

Я работаю над кодом Python, чтобы заменить выражение, содержащее «/», фактическим вызовом функции. Например: '(n/7-7) +(n/3+3)' должно стать '(div(n,7)-7 + ( div(n,3)+3)'. Обратите внимание только на '/ ' операнд необходимо заменить.

Для этого я использую ast.NodeVisitor.

class visitor(ast.NodeVisitor):
    def visit_Expression(self, node): return self.visit(node.body)
    def visit_Name(self, node): return node.id
    def visit_Constant(self, node): return str(node.value)
    def visit_UnaryOp(self, node): return f'{self.visit(node.op)}({self.visit(node.operand)})'
    def visit_UAdd(self, node): return '+'
    def visit_USub(self, node): return '-'
    def visit_BinOp(self, node): 
        if isinstance(node.op,ast.Div):
             return f'{self.visit(node.op)}({self.visit(node.left)},{self.visit(node.right)})'
        else:
            return f'{self.visit(node.left)} {self.visit(node.op)} {self.visit(node.right)}'
    def visit_Add(self, node): return '+'
    def visit_Sub(self, node): return '-'
    def visit_Mult(self, node): return '*'
    def visit_Div(self, node): return 'div'
    def generic_visit(self, node): raise ValueError('Invalid Token')

def tokenize(source):
    return visitor().visit(ast.parse(source, mode='eval'))

Я вызываю эту функцию как и получаю вывод div(n,5)-1:

    expression = 'n/5-1'
    expression = tokenize(expression)

Однако это не работает для тригонометрических функций, таких как tan/радианы. Например:

expression = 'tan(radians(top))'

Нужно ли мне также добавлять visit_tan и visit_radians?

Похоже, вам нужен NodeTransformer, а не NodeVisitor. Кроме того, этот метод действительно не должен возвращать строки.

user2357112 17.05.2024 13:03

Ты прав. Строки не должны быть возвращены.

user2695082 17.05.2024 13:27

Я изменю код, чтобы он возвращал строки для всех операндов, и попробую.

user2695082 17.05.2024 13:33
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
3
68
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Если вы намерены продолжать использовать свой нынешний подход, я не вижу причин, по которым вам нужно что-то еще, кроме текущего расширения ast.NodeVisitor.

Вы можете просто добавить в свой класс следующий метод:

class visitor(ast.NodeVisitor):
    # (...)
    def visit_Call(self, node): 
        return f'{self.visit(node.func)}({','.join(map(self.visit, node.args))})'

tokenize('tan(radians(n/7-7))')
# 'tan(radians(div(n,7) - 7))'

Это позволит прочитать любой вызов функции (например, rad, tan...) и снова записать его как вызов функции в результирующий текст. Если вы хотите ограничить их, чтобы разрешить только определенный список имен функций, вы можете поставить проверку внутри метода и отправлять visit(node.func) только в том случае, если node.func.id есть в вашем списке, в противном случае отправляйте generic_visit, чтобы он мог выдать ошибку.

Другие вопросы по теме