Mutually referencing imports -- impossible?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Matthew Wilson

    Mutually referencing imports -- impossible?

    I started off with a module that defined a class Vehicle, and then
    subclasses Car and Motorcycle.

    In the Car class, for some bizarre reason, I instantiated a Motorcycle.
    Please pretend that this can't be avoided for now.

    Meanwhile, my Motorcycle class instantiated a Car as well.

    Then I moved the Car and Motorcycle classes into separate files. Each
    imported the Vehicle module.

    Then I discovered that my Car module failed because the global
    Motorcycle wasn't defined. The same problem happened in my Motorcycle
    module. Car and Motorcycle can't both import each other.

    In the beginning, when all three (Vehicle, Car, and Motorcycle) were
    defined in the same file, everything worked fine.

    I don't know how to split them out in separate files now though and I
    really wish I could because the single file is enormous.

    Any ideas?

    Matt




  • Gary Herron

    #2
    Re: Mutually referencing imports -- impossible?

    Matthew Wilson wrote:
    I started off with a module that defined a class Vehicle, and then
    subclasses Car and Motorcycle.
    >
    In the Car class, for some bizarre reason, I instantiated a Motorcycle.
    Please pretend that this can't be avoided for now.
    >
    Meanwhile, my Motorcycle class instantiated a Car as well.
    >
    Then I moved the Car and Motorcycle classes into separate files. Each
    imported the Vehicle module.
    >
    Then I discovered that my Car module failed because the global
    Motorcycle wasn't defined. The same problem happened in my Motorcycle
    module. Car and Motorcycle can't both import each other.
    >
    In the beginning, when all three (Vehicle, Car, and Motorcycle) were
    defined in the same file, everything worked fine.
    >
    I don't know how to split them out in separate files now though and I
    really wish I could because the single file is enormous.
    >
    Any ideas?
    >
    Matt
    >
    It is easy for imports to be mutually referencing. This presents no
    problem to Python if the importing of one module is interrupted by the
    import of another.

    However, if one of them imports specific names from a module,
    from ABC import abc
    or
    from ABC import *

    then it's possible that the (interrupted) import of module ABC has not
    progressed to the point that abc is defined.

    The solution: Just
    import ABC
    and later reference ABC.abc

    That being said, it is still a good design practice to structure your
    modules hierarchically rather than a circularly.

    Gary Herron

    Comment

    • Carl Banks

      #3
      Re: Mutually referencing imports -- impossible?

      On Jul 13, 1:55 pm, Matthew Wilson <m...@tplus1.co mwrote:
      I started off with a module that defined a class Vehicle, and then
      subclasses Car and Motorcycle.
      >
      In the Car class,  for some bizarre reason, I instantiated a Motorcycle..
      Please pretend that this can't be avoided for now.
      >
      Meanwhile, my Motorcycle class instantiated a Car as well.
      >
      Then I moved the Car and Motorcycle classes into separate files.  Each
      imported the Vehicle module.
      >
      Then I discovered that my Car module failed because the global
      Motorcycle wasn't defined.  The same problem happened in my Motorcycle
      module.  Car and Motorcycle can't both import each other.
      >
      In the beginning, when all three (Vehicle, Car, and Motorcycle) were
      defined in the same file, everything worked fine.
      >
      I don't know how to split them out in separate files now though and I
      really wish I could because the single file is enormous.
      >
      Any ideas?
      First thing to do is ask yourself:
      Are the Car and Motorcycle being created at import time, or are they
      being created after the imports by a function call?

      If it's the former, then yes, it's impossible. You can't do this, for
      instance:

      car.py:
      -----------------
      import motorcycle
      a = motorcycle.Moto rcycle()
      -----------------

      motorcycle.py:
      -----------------
      import car
      b = car.Car()
      -----------------


      However, you can stick them in functions and call them afterwards and
      it will work:

      car.py:
      -----------------
      import motorcycle
      def create_motorcyc le():
      global a
      a = motorcycle.Moto rcycle()
      -----------------

      motorcycle.py:
      -----------------
      import car
      def create_car():
      global b
      a = car.Car()
      -----------------

      vehicle.py
      -----------------
      import car
      import motorcycle
      car.create_moto rcycle()
      motorcycle.crea te_car()
      -----------------


      Second, if you're using from ... import statements, it won't work; you
      should change it to use plain imports as I did above. So the
      following wouldn't work :


      motorcycle.py:
      -----------------
      from car import *
      a = Motorcycle()
      -----------------

      car.py:
      -----------------
      from motorcycle import *
      b = Car()
      -----------------



      Third, if Motorcycle and Car are inside packages, you still need to
      avoid from ... import even just to import the module (unless you're
      willing to hook into the import machinery). For example, if car.py,
      motorcycle.py, and vehicle.py are all parts of the package carsim,
      then you'd have to do this:

      motorcycle.py:
      ----------------
      import carsim.car
      def create_car():
      global a
      a = carsim.car.Car( )
      ----------------

      and not

      motorcycle.py:
      ----------------
      from carsim import car
      def create_car():
      global a
      a = car.Car()
      ----------------

      This last limitation is due to a wart in the import logic.


      Carl Banks

      Comment

      • John Roth

        #4
        Re: Mutually referencing imports -- impossible?

        On Jul 13, 11:55 am, Matthew Wilson <m...@tplus1.co mwrote:
        I started off with a module that defined a class Vehicle, and then
        subclasses Car and Motorcycle.
        >
        In the Car class,  for some bizarre reason, I instantiated a Motorcycle..
        Please pretend that this can't be avoided for now.
        >
        Meanwhile, my Motorcycle class instantiated a Car as well.
        >
        Then I moved the Car and Motorcycle classes into separate files.  Each
        imported the Vehicle module.
        >
        Then I discovered that my Car module failed because the global
        Motorcycle wasn't defined.  The same problem happened in my Motorcycle
        module.  Car and Motorcycle can't both import each other.
        >
        In the beginning, when all three (Vehicle, Car, and Motorcycle) were
        defined in the same file, everything worked fine.
        >
        I don't know how to split them out in separate files now though and I
        really wish I could because the single file is enormous.
        >
        Any ideas?
        >
        Matt
        While it's possible for circular imports to work, it's very dangerous:
        it's not always possible to tell what went wrong without tracking down
        the process of the import step by step. There are more productive ways
        of banging your head against the wall and going insane.

        In your situation, it might be a whole lot easier to extract a common
        superclass that both of your classes could inherit from.

        John Roth

        Comment

        • John Machin

          #5
          Re: Mutually referencing imports -- impossible?

          On Jul 14, 3:55 am, Matthew Wilson <m...@tplus1.co mwrote:
          I started off with a module that defined a class Vehicle, and then
          subclasses Car and Motorcycle.
          >
          In the Car class, for some bizarre reason, I instantiated a Motorcycle.
          Please pretend that this can't be avoided for now.
          >
          Meanwhile, my Motorcycle class instantiated a Car as well.
          >
          Then I moved the Car and Motorcycle classes into separate files. Each
          imported the Vehicle module.
          >
          Then I discovered that my Car module failed because the global
          Motorcycle wasn't defined. The same problem happened in my Motorcycle
          module. Car and Motorcycle can't both import each other.
          And they should not import each other.
          >
          In the beginning, when all three (Vehicle, Car, and Motorcycle) were
          defined in the same file, everything worked fine.
          You seem to have a strange notion of "worked fine".
          >
          I don't know how to split them out in separate files now though and I
          really wish I could because the single file is enormous.
          What is making a file with 3 classes "enormous"? ? What is "enormous"?
          >
          Any ideas?
          *WRONG WAY*
          *GO BACK*

          Your structure is not only bizarre, it is also (sticking with only 1
          letter of the alphabet) a Byzantine, baroque, and broken concept.

          Asking us to "pretend that this can't be avoided for now" is asking
          us to aid and abet you in creating a meaningless and unmaintainable
          monster. Consider adding Truck and Bus subclasses. Will each subclass
          instantiate the other 3??? You should be able to add or remove a
          subclass without having to modify all other subclasses.

          The only rational solution is not to have the subclasses refer to each
          other. Tell us *why* you think you need to have Car refer to
          Motorcycle and vice versa, and we should be able to help you find a
          way out.

          Cheers,
          John

          Comment

          • John Machin

            #6
            Re: Mutually referencing imports -- impossible?

            On Jul 14, 5:30 am, John Roth <johnro...@gmai l.comwrote:
            On Jul 13, 11:55 am, Matthew Wilson <m...@tplus1.co mwrote:
            >
            >
            >
            I started off with a module that defined a class Vehicle, and then
            subclasses Car and Motorcycle.
            >
            In the Car class, for some bizarre reason, I instantiated a Motorcycle.
            Please pretend that this can't be avoided for now.
            >
            Meanwhile, my Motorcycle class instantiated a Car as well.
            >
            Then I moved the Car and Motorcycle classes into separate files. Each
            imported the Vehicle module.
            >
            Then I discovered that my Car module failed because the global
            Motorcycle wasn't defined. The same problem happened in my Motorcycle
            module. Car and Motorcycle can't both import each other.
            >
            In the beginning, when all three (Vehicle, Car, and Motorcycle) were
            defined in the same file, everything worked fine.
            >
            I don't know how to split them out in separate files now though and I
            really wish I could because the single file is enormous.
            >
            Any ideas?
            >
            Matt
            >
            While it's possible for circular imports to work, it's very dangerous:
            it's not always possible to tell what went wrong without tracking down
            the process of the import step by step. There are more productive ways
            of banging your head against the wall and going insane.
            >
            In your situation, it might be a whole lot easier to extract a common
            superclass that both of your classes could inherit from.
            >
            Like the Vehicle class the OP mentioned?

            Comment

            Working...