0

I have the situation where I have two classes (Empire and City). An empire consists of many cities, so an instance of empire has a list of cities as an attribute. The city itself has an attribute of owner which links back to the empire. At present my code looks something like this:

Empire.py

import City

class Empire:
    def get_city_list(self):
        return self.city_list

    def add_city(self, city):
        assert(isinstance(city, City.City)), "Invalid city added to empire"
        self.city_list.append(city)
        city.owner = self

    def do_all_cities(self):
        for city in self.get_city_list():
            city.do_some_stuff() 

City.py

class City:

    def __init__(self):
        self.owner = None

    def get_owner(self):
        return self.owner

    def do_some_stuff(self):
         pass

    def do_some_other_stuff_that_requires_owner(self):
         pass

This all works fine, provided that I always use the add_city() method or manually set the owner of a city everytime I create one. If I don't, then I would have None as the owner and do_some_other_stuff_that_requires_owner would break down. I'd like to prevent this possible source of errors by having something like

City.py

import Empire

class City:

    def __init__(self, owner):
        assert(isinstance(owner, Empire.Empire)), "Invalid empire as owner"
        self.owner = owner

    ....

This makes me more comfortable that everything is of the right type (even if it is less pythonic). The problem with this is the circular import. While it does work, circular imports make me nervous and I was under the impression that they should be avoided.

What is the correct way of solving this problem? I have two separate modules that each need to check that an object is an instance of a class belonging another module.

[PS: I know getters and setters aren't very pythonic, but I'm doing this project partly to get to know OOP well and to get into some good habits]

EDIT: One possible answer has been suggested, which is various ways of having circular imports. From casual discussions, I've heard that circular imports are a sign that the code is badly structured and should be refactorised. Is this preferable? If so, how should it be done here?

ScienceSnake
  • 608
  • 4
  • 15
  • The best way is to use a third `.py` file which imports both `City` and `Empire`. However, in your example, it is fine. It's only when you do `from City import ...` then it becomes an issue. – Robert Seaman Apr 23 '17 at 11:53
  • 1
    It makes sense that until you add a city to an empire it has no owner – stark Apr 23 '17 at 12:20
  • Stark, I agree, but I want to make it impossible to create city that doesn't belong to an empire. Robert: Exactly how would I do this with a third python file. Do you have an example? – ScienceSnake Apr 23 '17 at 14:00
  • 1
    Your options are explained well in this answer: http://stackoverflow.com/a/37126790/7517724 – Craig Apr 23 '17 at 14:34

0 Answers0