web-dev-qa-db-fra.com

Dépendance circulaire en Python

J'ai deux fichiers, node.py et path.py, qui définissent deux classes, Node et Path, respectivement.

Jusqu'à aujourd'hui, la définition de Path faisait référence à l'objet Node, et donc j'avais fait

from node.py import *

dans le path.py fichier.

Cependant, à partir d'aujourd'hui, j'ai créé une nouvelle méthode pour Node qui fait référence à l'objet Path.

J'ai rencontré des problèmes lors de l'importation de path.py: Je l'ai essayé, et lorsque le programme s'est exécuté et a appelé la méthode Path qui utilise Node, une exception s'est levée à propos de Node non définie.

Que fais-je?

59
Ram Rachum

Importation Python Modules est un excellent article qui explique les importations circulaires en Python.

Le moyen le plus simple de résoudre ce problème consiste à déplacer l'importation de chemin d'accès à la fin du module de nœud.

103
Nadia Alramli

Une autre approche consiste à importer l'un des deux modules niquement dans la fonction là où vous en avez besoin dans l'autre. Bien sûr, cela fonctionne mieux si vous n'en avez besoin que dans une ou un petit nombre de fonctions:

# in node.py 
from path import Path
class Node 
    ...

# in path.py
class Path
  def method_needs_node(): 
    from node import Node
    n = Node()
    ...
22
mircealungu

Je préfère briser une dépendance circulaire en déclarant l'une des dépendances dans le constructeur de l'autre classe dépendante. À mon avis, cela maintient le code plus propre et donne un accès facile à toutes les méthodes qui nécessitent la dépendance.

Donc, dans mon cas, j'ai un CustomerService et un UserService qui dépendent l'un de l'autre. Je romps la dépendance circulaire comme suit:

class UserService:

    def __init__(self):
        # Declared in constructor to avoid circular dependency
        from server.portal.services.admin.customer_service import CustomerService
        self.customer_service = CustomerService()

    def create_user(self, customer_id: int) -> User:
        # Now easy to access the dependency from any method
        customer = self.customer_service.get_by_id(customer_id)
1
Iain Hunter