python circular imports once again (aka what’s wrong with this design)

Circular imports are not inherently a bad thing. It’s natural for the team code to rely on user whilst the user does something with team.

The worse practice here is from module import member. The team module is trying to get the user class at import-time, and the user module is trying to get the team class. But the team class doesn’t exist yet because you’re still at the first line of team.py when user.py is run.

Instead, import only modules. This results in clearer namespacing, makes later monkey-patching possible, and solves the import problem. Because you’re only importing the module at import-time, you don’t care than the class inside it isn’t defined yet. By the time you get around to using the class, it will be.

So, test/users.py:

import test.teams

class User:
    def setTeam(self, t):
        if isinstance(t, test.teams.Team):
            self.team = t

test/teams.py:

import test.users

class Team:
    def setLeader(self, u):
        if isinstance(u, test.users.User):
            self.leader = u

from test import teams and then teams.Team is also OK, if you want to write test less. That’s still importing a module, not a module member.

Also, if Team and User are relatively simple, put them in the same module. You don’t need to follow the Java one-class-per-file idiom. The isinstance testing and set methods also scream unpythonic-Java-wart to me; depending on what you’re doing you may very well be better off using a plain, non-type-checked @property.

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)