Module Structure/Import Design Problem

Steve Holden steve at holdenweb.com
Thu Nov 20 22:46:14 EST 2008


Rafe wrote:
> On Nov 21, 1:39 am, Steve Holden <st... at holdenweb.com> wrote:
>> Rafe wrote:
>>> Hi,
>>> I am in a situation where I feel I am being forced to abandon a clean
>>> module structure in favor of a large single module. If anyone can save
>>> my sanity here I would be forever grateful.
>>> My problem is that classes in several modules share a common base
>>> class which needs to implement a factory method to return instances of
>>> these same classes.
>>> An example to help illustrate what I mean:
>>> Lets say I have the following modules with the listed classes:
>>>  - baselib.py   with  BaseClass
>>>  - types.py   with  TypeA, ...
>>>  - special.py   with  SpecialTypeA, ...
>>> Which would be used a bit like this:
>>>>>> type_a = any_type_instance.get_type("TypeA")
>>>>>> special_type = type_a.get_type("SpecialTypeA")
>>> Again, I can get around this by dumping everything in to one module,
>>> but it muddies the organization of the package a bit. This seems like
>>> a problem that would come up a lot. Are there any design paradigms I
>>> can apply here?
>> Well a simple way to do this is to observe that even when a base class's
>> method is inherited by an instance of a subclass, when the method is
>> called the type of "self" is the subclass. And you can call the
>> subclass's type to create an instance. Perhaps the following  code would
>> make it more obvious:
>>
>> $ cat baseclass.py
>> class Base(object):
>>     def factory(self, arg):
>>         return type(self)(arg)
>>
>> sholden at lifeboy /c/Users/sholden/Projects/Python
>> $ cat subclass.py
>> from baseclass import Base
>>
>> class sub(Base):
>>   def __init__(self, arg):
>>     print "Creating a sub with arg", arg
>>
>> s = sub("Manual")
>>
>> thing = s.factory("Auto")
>> print type(thing)
>>
>> sholden at lifeboy /c/Users/sholden/Projects/Python
>> $ python subclass.py
>> Creating a sub with arg Manual
>> Creating a sub with arg Auto
>> <class '__main__.sub'>
>>
>> Hope this helps.
>>
>> regards
>>  Steve
>> --
>> Steve Holden        +1 571 484 6266   +1 800 494 3119
>> Holden Web LLC              http://www.holdenweb.com/
> 
> Hi Steve,
> 
> Correct me if I have this wrong, but the problem with your solution is
> that it only creates a new instance of the same class, type(self),
> while I need to return any number of different possibilities.
> 
In that case you need to pass the type of the new instance you require
as an argument to the factory method, I guess, or something similar. My
example has each subclass returning instances of the subclass that was
used to call the factory method, yes.

If A instances need to be able to get B instances and B instances need
to be able to create B instances then you do indeed have a tricky
problem when it comes to separating your classes into different
modules,. But it's not insoluble!

> I thought about getting the module from self...
>>>> class base(object):
>>>>     def factory(self, type):
>>>>         module = sys.modules[self.__class__.__module__]
>>>>         return getattr(module, type)
> 
> ...but my baseclass is used from several modules so this would be
> inaccurate for me (the factory method only uses my 'types' module, so
> a hard import works)
> 
I am not sure yet if I understand the requirement properly. It seems
from the above code that you always want to create instances of a named
type defined in the same module as the subclass?

> I'm still wondering what Arnaud meant by "make types register
> themselves with the factory function"
> 
You would have to ask him, but I suspect he means having each subtype
call a method of the base type to add itself to some dictionary so you
can call the factory method with a key that will tell it which subtype
to produce. This is a fairly sensible way to separate definitions form
references.

regards
 Steve
-- 
Steve Holden        +1 571 484 6266   +1 800 494 3119
Holden Web LLC              http://www.holdenweb.com/




More information about the Python-list mailing list