Круговой импорт при использовании строгой проверки типа stati c - PullRequest
0 голосов
/ 07 апреля 2020

Я работаю над проектом, и я решил go с этой диаграммой классов:

Во время тестов все работало нормально поэтому я решил сделать это правильно и убедиться, что все типы были указаны просто, чтобы избежать проблем в будущем. Проблема в том, что для этого мне нужно импортировать больше классов, и я получаю циклический импорт.

В некоторых местах я читал, что эта проблема обычно из-за плохого дизайна. Я не думаю, что это так. В других местах я читал, что не должен проверять типы. Это вариант, но он мне не нравится. Я также читал о других способах решения этой проблемы, но ни один из них, кажется, не является реальным решением.

Я знаю, что Python не Java, но поскольку импорт, который создает мои проблемы, просто использовал для указания типа параметров методов Я думал, что, возможно, есть способ указать это внутри программы python, чтобы при круговом импорте не избежать выполнения программы.

Спасибо, если вам нужна какая-либо другая информация, просто спросите, и я отвечу как можно скорее.

РЕДАКТИРОВАТЬ:

Это вывод терминала:

[edoelas@leonardo server]$ env DEBUGPY_LAUNCHER_PORT=44765 /usr/bin/python /home/edoelas/.vscode/extensions/ms-python.python-2020.3.71113/pythonFiles/lib/python/debugpy/no_wheels/debugpy/launcher /home/edoelas/git/tfg/server/main.py 
Traceback (most recent call last):
  File "/home/edoelas/git/tfg/server/main.py", line 1, in <module>
    from classes.actions.Move import Move
  File "/home/edoelas/git/tfg/server/classes/actions/Move.py", line 2, in <module>
    from classes.Entity import Entity
  File "/home/edoelas/git/tfg/server/classes/Entity.py", line 3, in <module>
    from classes.ActionType import ActionType
  File "/home/edoelas/git/tfg/server/classes/ActionType.py", line 5, in <module>
    from classes.Entity import Entity 
ImportError: cannot import name 'Entity' from partially initialized module 'classes.Entity' (most likely due to a circular import) (/home/edoelas/git/tfg/server/classes/Entity.py)

И вот эти файлы:

Main.py

from classes.actions.Move import Move
from classes.Position import Position
from classes.Game import Game
from classes.Entity import Entity
from classes.Client import Client
from classes.Map import Map



if __name__ == "__main__":

    map1 = Map()

    client1 = Client("localhost",1000)
    position1 = Position(0,0)
    action1 = Move()
    entity1 = Entity("test",100,1,[action1],client1,position1,map1)
    id1 = 1
    entity1.id = id1

    ground_matrix = [
        [0,0,0,0],
        [0,0,0,0],
        [0,0,0,0],
        [0,0,0,0],
    ]

    entity_matrix = [
        [id1,0,0,0],
        [0,0,0,0],
        [0,0,0,0],
        [0,0,0,0],
    ]
    map1.load_map(ground_matrix,entity_matrix)

    game = Game("ip", 1000, "asd")
    game.add_entity(entity1)

    print(map1.entity_matrix)
    print(entity1.position)

    position2 = Position(1,0)
    entity1.loadAction(action1,position2)
    entity1.executeAction()

    action1.emiting_area

    print(map1.entity_matrix)
    print(entity1.position)

Move.py

from classes.Position import Position
from classes.Entity import Entity
from classes.ActionType import ActionType
from classes.Area import Area

class Move(ActionType):
    def __init__(self):
        self.emiting_area

    @property
    def emiting_area(self) -> Area:
        return self.__emiting_area

    @emiting_area.setter
    def emiting_area(self, emiting_area: Area) -> None:
        self.__emiting_area = emiting_area

    def execute(self,emitter: Entity,target_position: Position) -> None:
        emitter.position = target_position

Entity.py

# pyright: strict

from classes.ActionType import ActionType
from classes.Map import Map
from classes.Position import Position
from classes.Client import Client
from classes.Action import Action
from typing import List

class Entity:
    """
    The entities are added from the Game object
    """
    def __init__(self, name: str, max_health: int,team: int,
    possible_actions: List[ActionType], client: Client,position: Position,map: Map):
        self.__id: int
        self.__name: str = name
        self.max_health: int= max_health
        self.team: int = team
        self.health: int = max_health
        self.possible_actions: List[ActionType] = possible_actions
        self.__action_buffer: List[Action] = []
        self.client: Client = client
        self.__position: Position = position
        #Map is here in order to update it each time an entity moves
        self.map: Map = map


    @property
    def position(self) -> Position:
        return self.__position

    @position.setter
    def position(self, new_position: Position):
        self.__position = new_position
        self.map.update_entity(self.id,self.__position,new_position)


    @property
    def id(self) -> int:
        return self.__id

    @id.setter
    def id(self,id: int):
        #Si la id ya ha sido asignada lanzar error
        self.__id = id


    def loadAction(self,actionType: ActionType,target_position: Position) -> None:
        action = Action(actionType, self,target_position)
        self.__action_buffer.append(action)

    def executeAction(self) -> None:
        action = self.__action_buffer.pop(0)
        action.execute()

ActionType.py

# pyright: strict

from abc import abstractmethod
from classes.Position import Position
from classes.Entity import Entity 

class ActionType:
    def __init__(self):
        raise NotImplementedError

    @property
    @abstractmethod
    def emiting_area(self) -> None:
        raise NotImplementedError

    @property
    @abstractmethod
    def receiving_area(self) -> None:
        raise NotImplementedError

    @abstractmethod
    def execute(self,emiter: Entity,target_position: Position) -> None:
        raise NotImplementedError
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...