apeks
@apeks
Очень серьезный человек

Как переопределить if в python?

Увидел пример введения своего варианта if в Lisp Scheme

(define (new-if predicate then-clause else-clause)
    (cond (predicate then-clause)
    (else else-clause)))


как так же сделать в python и есть ли вообще возможность переопределить поведение if или любого другого ключевого слова?
  • Вопрос задан
  • 352 просмотра
Решения вопроса 1
sergey-gornostaev
@sergey-gornostaev Куратор тега Python
Седой и строгий
Прежде всего хочу заметить, что настолько больших возможностей по расширению языка, как в Lisp'ах, никакой другой язык не предоставляет. Но в некоторых языках, в том числе в Python, можно немного поколдовать с кодом на этапе его разбора.

dumb_translator.py
import ast
import sys

class DumbLisp(ast.NodeTransformer):
    def fix(self, source, result):
        ast.copy_location(result, source)
        ast.fix_missing_locations(result)
        return result

    def visit_Expr(self, node):
        if isinstance(node.value, ast.Tuple):
            t = node.value
            if isinstance(t.elts[0], ast.Name):
                if t.elts[0].id == 'newif':
                    _else = [ast.Expr(value=t.elts[3])] if len(t.elts) == 4 else []
                    _if = ast.If(test=t.elts[1],
                                body=[ast.Expr(value=t.elts[2])],
                                orelse=_else)
                    self.generic_visit(_if)
                    return self.fix(node, _if)
                elif t.elts[0].id == 'define':
                    assign = ast.Assign(targets=[ast.Name(id=t.elts[1].id, ctx=ast.Store())],
                                        value=t.elts[2])
                    return self.fix(node, assign)
                else:
                    call = ast.Expr(value=ast.Call(func=t.elts[0], args=t.elts[1:], keywords=[]))
                    return self.fix(node, call)
        return node


with open(sys.argv[1]) as fh:
    tree = ast.parse(fh.read())
    DumbLisp().visit(tree)
    code = compile(tree, filename=sys.argv[1], mode="exec")
    exec(code)

test.dl
(define, a, 1)

(newif, a == 1, (print, 'Yes'), (print, 'No'))

Запускаем
python dumb_translator.py test.dl

Естественно, пример предельно простой, а потому в качестве s-форм приходится использовать кортежи. Но есть полноценный фронтенд компилятора Python, транслирующий в python-байткод диалект Lisp близкий к Clojure - Hy.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы