pythonpython-importpython-typingattributeerrorvisitor-pattern

Python 3.5 type hinting gives "AttributeError: module 'iterator_function' has no attribute 'IteratorFunction'"


When I try to type hint to my custom class, python will throw an AttributeError on 'module.class'. Intellisence tells me, the import is right and the class can be found.

function_dispatcher.py, it goes wrong in this file at : iterator_function.IteratorFunction. When I remove the particular type hint, the program will run fine.

from abc import ABC, abstractclassmethod
import iterator_function

class FunctionDispatcher(ABC):
    @abstractclassmethod
    def dispatch(self, function : iterator_function.IteratorFunction):
        pass

iterator_function.py, this is the imported class. Notice: the type hinting to : function_dispatcher.FunctionDispatcher works here.

import function
import function_dispatcher

class IteratorFunction(function.Function):
    def accept(self, dispatcher : function_dispatcher.FunctionDispatcher):
        dispatcher.dispatch(self)

This is the traceback output:

1>  Traceback (most recent call last):
1>    File "C:\Users\admin\Documents\visual studio 2015\Projects\Preprocessor\Program\preprocessor\main.py", line 1, in <module>
1>      import generator
1>    File "C:\Users\admin\Documents\visual studio 2015\Projects\Preprocessor\Program\preprocessor\generator.py", line 3, in <module>
1>      from iterator_function import IteratorFunction
1>    File "C:\Users\admin\Documents\visual studio 2015\Projects\Preprocessor\Program\preprocessor\iterator_function.py", line 1, in <module>
1>      import function
1>    File "C:\Users\admin\Documents\visual studio 2015\Projects\Preprocessor\Program\preprocessor\function.py", line 2, in <module>
1>      import function_dispatcher
1>    File "C:\Users\admin\Documents\visual studio 2015\Projects\Preprocessor\Program\preprocessor\function_dispatcher.py", line 4, in <module>
1>      class FunctionDispatcher(ABC):
1>    File "C:\Users\admin\Documents\visual studio 2015\Projects\Preprocessor\Program\preprocessor\function_dispatcher.py", line 6, in FunctionDispatcher
1>      def dispatch(self, function : iterator_function.IteratorFunction):
1>  AttributeError: module 'iterator_function' has no attribute 'IteratorFunction'

For anyone wondering what I am trying to do: implementing the visitor pattern.


Solution

  • hiro protagonist was right. I was able to solve the circular import and maintain the type checking. It is not as clean but it does the job.

    function.py

    from abc import ABC, abstractmethod
    
    class Function(ABC):
        def __init__(self, arguments, min_arguments):
            self.arguments = arguments
            self.min_arguments = min_arguments if len(arguments) < min_arguments else len(arguments)
    
        @abstractmethod
        def accept(self, dispatcher):
            pass
    
        def test_dispatcher(self, dispatcher):
            import function_dispatcher
            if not isinstance(dispatcher, function_dispatcher.FunctionDispatcher):
                raise Exception("Not of type FunctionDispatcher")
    

    iterator_function.py

    import function
    
    class IteratorFunction(function.Function):
        def accept(self, dispatcher):
            self.test_dispatcher(dispatcher)
            dispatcher.dispatch(self)