1

I have just faced with with behaviour I don't yet understand and don't know how to name it. I'll reproduce it here.

Let's say we have a project with the structure as lined below.

src
│   __init__.py
│   main.py
│
└───utils
    │   __init__.py
    │   data.py
    └───funcs.py

First, inside utils.data we define two classes.

# utils.data module

__all__ = [
    'Menu',
    'Case'
]

from enum import Enum

class Menu(Enum):
    QUIT = 'exit'

class Case:
    def __init__(self):
        self.a = 7

Then inside utils.funcs we define two functions to return instances of those classes.

# utils.funcs module

__all__ = [
    'get_Menu_instance',
    'get_Case_instance',
]

from src.utils import data

def get_Menu_instance():
    return data.Menu.QUIT

def get_Case_instance():
    return data.Case()

Finally, in main we call both functions. And check if result and expected inherit from the respective classes.

# main module

import utils

def main():
    result = utils.get_Menu_instance()
    expected = utils.Menu.QUIT
    print(f'{isinstance(result, utils.Menu) = }\n'
          f'{isinstance(expected, utils.Menu) = }\n')

    result = utils.get_Case_instance()
    expected = utils.Case()
    print(f'{isinstance(result, utils.Case) = }\n'
          f'{isinstance(expected, utils.Case) = }\n')

if __name__ == '__main__':
    main()

Here the Magic comes. An output of main() depends on relative or absolute import in utils.__init__ .

relative absolute
# utils.init module

from .data import *
from .funcs import *
# utils.init module

from src.utils.data import *
from src.utils.funcs import *
> py main.py

isinstance(result, utils.Menu) = False
isinstance(expected, utils.Menu) = True

isinstance(result, utils.Case) = False
isinstance(expected, utils.Case) = True
> py main.py

isinstance(result, utils.Menu) = True
isinstance(expected, utils.Menu) = True

isinstance(result, utils.Case) = True
isinstance(expected, utils.Case) = True

Most far I understand by myself, is that there are two different class objects for each class: inside and outside a package. But what I can't get is how it could depend on relative or absolute import.

I would very appreciate if someone explain me it.

Thanks!

Gennadiy
  • 192
  • 10

0 Answers0