Consider the two modules (in the same folder):
firstly, person.py
from typing import List
from .pet import Pet
class Person:
def __init__(self, name: str):
self.name = name
self.pets: List[Pet] = []
def adopt_a_pet(self, pet_name: str):
self.pets.append(Pet(pet_name, self))
and then pet.py
from .person import Person
class Pet:
def __init__(self, name: str, owner: Person):
self.name = name
self.owner = owner
the code above will not work, because of circular dependency. You'll get an error:
ImportError: cannot import name 'Person'
Some ways to make it work:
- keep the definition of the classes Person and Pet in the same file.
- do away with the pet.owner attribute (which is there as a convenient pointer)
- don't use type-hinting / annotation where it would cause circular references:
e.g. just have:
class Pet:
def __init__(self, name: str, owner):
I see some drawback in all the options I've listed so far.
Is there another way? One that allows me to
- split classes into different files
- use type annotation in combined with pointers such as shown
Or: is there very good reason to instead follow one of the solutions I've already listed?
from .person import Person
to import the modulefrom . import person
and use the long nameperson.Person
(same for pet.Pet). The explanation was given here at SO already, don't want to duplicate it. – Quesenberryfrom demo import person charlie = person.Person('Charlie') charlie.adopt_pet('Lassie')
– Earthapython3 -m pkg.person
. I made the chances from my first comment. – Quesenberry