способ переопределить операторы? (для создания грубого компилятора)

#python #python-3.x

#python #python-3.x

Вопрос:

например, если бы я хотел сделать вместо

1 1 = 2

это было бы что-то вроде

» » = print(«add %d %d» % (a, b))

который будет интерпретироваться как

1 1 = «добавить 1 1»

Я хочу использовать это при использовании python в качестве контейнера для хранения логики, а затем легко преобразовать ее на другой язык (проприетарный язык под названием huff, который похож на сборку на виртуальной машине ethereum)

Комментарии:

1. Поведение операторов зависит от объектов, которые им даны. Вам нужно будет обернуть данные в некоторый класс-оболочку и переопределить поведение в оболочке.

2. Я сейчас нахожусь на своем телефоне, так что, к сожалению, это было бы болезненно. В частности, вам нужно будет написать __add__ метод в классе, чтобы изменить поведение. Также обратите внимание, что вы столкнетесь с проблемой при работе с = / mov translations (я предполагаю, что ваш целевой язык имеет операцию a mov -like ). Вы не можете переопределить поведение присваивания, так что это будет еще одна проблема. Возможно, вам придется подумать об этом с другой стороны и использовать ast модуль для синтаксического анализа Python, а затем вручную перевести этот AST на ваш целевой язык.

3. Я удалил свой предыдущий комментарий, потому что здесь запрещено запрашивать код, мой плохой!

Ответ №1:

Поскольку Python не позволяет переопределять атрибуты встроенных типов:

 int.__add__ = lambda self, other: 'add {} {}'.format(self, other)

TypeError: can't set attributes of built-in/extension type 'int'
  

Вам нужно будет реализовать свой собственный класс, который будет служить оболочкой для int .

 class MyInt(int):
    def __add__(self, other):
        # TODO handle the case the condition is false
        if isinstance(other, self.__class__):
            return 'add {} {}'.format(self, other)

x = MyInt(1)   MyInt(2)
print(x)
# add 1 2
  

Проверка может быть изменена на более мягкую issubclass(other.__class__, int) , которая позволит правильному операнду быть «нормальным» целым числом:

 class MyInt(int):
    def __add__(self, other):
        # TODO handle the case the condition is false
        if issubclass(other.__class__, int):
            return 'add {} {}'.format(self, other)

x = MyInt(1)   2
print(x)
# add 1 2
  

Тогда вы также можете захотеть реализовать __radd__ , по крайней мере, ассоциативную операцию:

 class MyInt(int):
    def __add__(self, other):
        # TODO handle the case the condition is false
        if issubclass(other.__class__, int):
            return 'add {} {}'.format(self, other)

    def __radd__(self, other):
        # TODO handle the case the condition is false
        if issubclass(other.__class__, int):
            return 'add {} {}'.format(other, self)

x = 2   MyInt(1)
print(x)
# add 2 1
  

Комментарии:

1.@Alita Ты не можешь. Python не позволяет переопределять атрибуты встроенных типов. int.__add__ = lambda self, other: 'add {} {}'.format(self, other) TypeError: can't set attributes of built-in/extension type 'int'

2. Если вы действительно хотите переопределить встроенные методы, всегда forbiddenfruit есть модуль.

3. @Axe319 со страницы pypi: "but it may lead you to hell if used on production code" нужно ли мне говорить больше?

4. Не совсем, lol @DeepSpace Я бы никогда не использовал его лично, но это то, о чем они просили.

5. @DeepSpace Я попытался вручную определить __add__ функцию ранее def __add__(self, other): return f'add {self} {other}' , а затем использовать curse(int, '__add__', __add__) , и она работала нормально. Может быть, это не работает с лямбдами? Но это должно быть.