2

examiner les deux modules (dans le même dossier):Comment éviter la dépendance circulaire provoquée par le type de pointeur faisant allusion attributs dans python

d'une part, person.py

from typing import List 
from .pet import Pet 


class Person: 
    def __init__(self, name: str): 
     self.name = name 
     self.pets = [] # type: List[Pet] 

    def adopt_a_pet(self, pet_name: str): 
     self.pets.append(Pet(pet_name)) 

puis pet.py

from .person import Person 


class Pet: 
    def __init__(self, name: str, owner: Person): 
     self.name = name 
     self.owner = owner 

le code ci-dessus ne fonctionnera pas, en raison de la dépendance circulaire. Vous obtiendrez une erreur:

ImportError: cannot import name 'Person' 

Voici quelques façons de le faire fonctionner:

  1. garder la définition des classes et personne pour animaux de compagnie dans le même fichier.
  2. éliminons l'attribut pet.owner (qui est là comme un pointeur pratique)
  3. ne pas utiliser de type hinting/annotation où il causerait des références circulaires:

par exemple juste avoir:

class Pet: 
    def __init__(self, name: str, owner): 

Je vois un inconvénient dans toutes les options que j'ai énumérées jusqu'à présent.

Existe-t-il un autre moyen? qui me permet de

  • partage des classes dans des fichiers différents
  • utilisation annotation de type en combinaison avec des pointeurs tels que montré

Ou: est-il très bonne raison de suivre plutôt que l'une des solutions J'ai déjà listé?

+0

Souvent, il est utile d'utiliser 'from .person import Person' pour importer le module' from. importer la personne et utiliser le nom long 'person.Person' (même chose pour pet.Pet). L'explication a déjà été donnée ici à SO, ne veut pas le dupliquer. – VPfB

+0

Pouvez-vous me diriger vers cette explication? J'ai essayé votre suggestion mais j'obtiens une erreur du fichier pet.py indiquant: AttributeError: module 'demo.person 'n'a pas d'attribut' Person ' Pour moi, cela est logique car la classe Pet est importée * lors de * l'importation de la classe Person, donc, au moment de l'importation de Pet, il n'y a pas encore de classe Person importée . – levraininjaneer

+0

Je me souviens d'une réponse de M. Pieters. La question était la mienne et la réponse explique la différence entre la dépendance sur le contenu du module et l'existence du module. Lien https://stackoverflow.com/questions/36137093/why-has-the-cyclical-import-issue-disappeared J'espère que cela vous aidera, car cela m'a aidé. – VPfB

Répondre

0

Après un peu plus d'apprentissage, j'ai réalisé il y a une bonne façon de le faire: Héritage:

D'abord, je définis personne, sans [animaux] ou la méthode dans l'OP. Ensuite, je définis Animaux, avec un propriétaire de classe Personne. Je définit

from typing import List 
from .person import Person 
from .pet import Pet 


class PetOwner(Person): 
    def __init__(self, name: str): 
     super().__init__(name) 
     self.pets = [] # type: List[Pet] 


    def adopt_a_pet(self, pet_name: str): 
     self.pets.append(Pet(pet_name)) 

Toutes les méthodes en personne qui a besoin de se référer à l'animal devrait être défini maintenant dans PetOwner et toutes les méthodes/attributs de la personne qui sont utilisés dans Pet doivent être définies en personne. Si le besoin se fait sentir d'utiliser des méthodes/attributs dans Pet qui ne sont présents que dans PetOwner, une nouvelle classe enfant de Pet, par ex. OwnedPet devrait être défini.

Bien sûr, si le nom me dérange, je pourrais changer de Person et PetOwner pour respectivement BasePerson et Person ou quelque chose comme ça.