Python - есть ли способ сделать набор текста, который объявлен позже - PullRequest
0 голосов
/ 07 июня 2019

Я занимался парсингом, и я хочу немного "набрать" в моем коде подсказки для типов. Но на классы файла ссылались и наследовали друг друга. Итак, мой код теперь спагетти: (

Я пробовал множество случаев, которые я могу сделать. Я попробовал все в одном классе, и я изменил порядок. Но ничего не изменилось. Тем не менее, есть ошибки вроде «Неразрешенная ссылка»

from abc import ABC, abstractmethod

class Expression(ABC):
    class Visitor(ABC):
        @abstractmethod
        def visit_assign(self, expr: Assign):
            pass

    @abstractmethod
    def accept(self, visitor: Visitor):
        pass

class Assign(Expression):
    def accept(self, visitor: Visitor):
        # ...

Назначение было объявлено позже класса посетителя. Итак, возникает ошибка «Неразрешенная ссылка».

Ответы [ 2 ]

0 голосов
/ 07 июня 2019

Есть два способа сделать это.

Первый - запустить from __future__ import annotations, который откладывает разбор аннотаций до времени выполнения, позволяя вашему коду работать без изменений.

Второй - изменить аннотации вашего типа на строки , что дает практически тот же эффект:

from abc import ABC, abstractmethod

class Expression(ABC):
    class Visitor(ABC):
        @abstractmethod
        def visit_assign(self, expr: 'Assign'):
            pass

    @abstractmethod
    def accept(self, visitor: 'Visitor'):  # not needed; for consistency only
        pass

class Assign(Expression):
    def accept(self, visitor: 'Visitor'):
        pass
0 голосов
/ 07 июня 2019

Решение проблем перекрестных ссылок может заключаться в том, чтобы сначала объявить, что вы можете, а позже добавить остальные.

Таким образом, вы можете получить что-то вроде:

from abc, import ABC, abstractmethod

class Expression(ABC):
    class Visitor(ABC):
        pass

class Assign(Expression):
    def accept(self, visitor: Visitor):
        # ...

@abstractmethod
def visit_assign(self, expr: Assign):
    pass

@abstractmethod
def accept(self, visitor: Visitor):
    pass

Expression.Visitor.visit_assign = visit_assign
Expression.accept = accept
...