Import order question
Dave Angel
davea at davea.name
Mon Feb 17 13:33:10 EST 2014
Terry Reedy <tjreedy at udel.edu> Wrote in message:
> On 2/17/2014 8:01 AM, Nagy László Zsolt wrote:
>> I have a class hierarchy like this:
>>
>> Widget <- VisualWidget <- BsWidget
>>
>> and then BsWidget has many descendants: Desktop, Row, Column, Navbar etc.
>>
>> Widgets can have children. They are stored in a tree. In order to manage
>> the order of widgets, I need methods to append children. (And later:
>> insert or prepend because they also have an order). So I would like to
>> have methods like this:
>>
>> BsWidget.AppendNavbar(....)
>> BsWidget.AppendRow(...)
>
> I would write one prepend/insert/append method that
> prepends/inserts/appends the widget passed.
>
>> Here is the problem: these methods should create instances of Row,
>> Column and Navbar.
>
> I disagree, without strong justification. Create the instances by
> directly calling the classes and do with them as you want.
>
I agree with Terry, and will try to justify it. Whenever you have
a large group of modules recursively importing each other, you
need to look hard at the reason. (And saying ' because java does
it that way' isn't a good enough one). Chances are things are
too coupled.
Your reason is because you have a base class instantiating child
classes, for most if not all its children. Problem with that is
you then need to modify that base class in about 4 places each
time you add a child class. Very messy.
So how do you avoid modifying the base class? Have an instance
passed in, instead, as Terry implied.
Now you say you don't want the application code to have to import
all of those child classes? There are several solutions to that,
depending.
You can make a module which imports each of those, and stores a
reference to each class. That becomes the only place to modify
as new ones are added.
Or you can have each of these extra modules add its factory
function to a common list or dict, either at import time or in a
once-called function. That common list could be defined (with
only the base class in it initially) in the module with the base
class.
You could even add these methods you're trying to define to the
base class, by defining them as ordinary functions in the
corresponding module, and adding the appropriate attribute to the
base.
Or you could have each new class add itself as a top level module
attribute to the module you plan for your users to
import.
Many more choices with various tradeoffs, and the best depends on
a number of factors not yet discussed. For example, do all
these classes take the same arguments to __init__? If so, then a
single factory that takes the class reference as a parameter
might be useful.
--
DaveA
More information about the Python-list
mailing list