Borg vs. Module

Carl Banks pavlovevidence at gmail.com
Tue Aug 1 07:11:10 EDT 2006


tobiah wrote:
> I am making a web app, made up of many modules
> that all need access to some important data, like
> the current session data, cookies, navigation history,
> post/get variables, etc.
>
> I decided to go with the 'Borg' idea, by assigning the
> __dict__ of an object to a class variable so that each
> instantiation of the Borg() would share the same data.
> That way I can either pass the Borg around, or just
> Borg() it if I need it in some obscure place.
>
> Then I read an argument that it usually makes more sense
> to just have a module with the data and functions that
> I need, which all the other modules can simply import.
> Since I only need one instance, I could just stuff data
> and call 'methods' on this module, probably without even
> changing existing syntax.
>
> Are there any arguments as to which method is better?

I would recommend a module over a Borg class simply because it's less
of a hack.

One thing that I never liked about using modules as classes was the
constant need to use the global statement when rebinding any module
level variables.  For that reason, if there was a lot of rebinding, I
would rewrite the module as a singleton class.  That had its own
problems; most significantly, it was a thorn in my side for
initializing things in the right order.  (My current project used lots
of circular imports which made things a lot worse.)

I finally lost my patience and decided to pull that thorn out by
converting the singletons back to modules.  That's when I came up with
this little decorator that obviates the need to use global statements,
plus it lets the module look and mostly act like a class.

def modmethod(func):
    class modproxy(object):
        __getattribute__ = func.func_globals.__getitem__
        __setattr__ = func.func_globals.__setitem__
    self = modproxy()
    def call_with_method(*args,**kwargs):
        return func(self,*args,**kwargs)
    call_with_method.func_name = func.func_name
    return call_with_method

This decorator means the function will get called with the module
(actually a proxy) as the first argument.  That way, you can access
module-level variable exactly like you would access instance variables
in a class, i.e., via self.

I was able to convert all my singletons to modules simply by dedenting
one level, and prefixing all the methods with @modmethod.  This worked
so sweetly it this is now my slam dunk recommendation for implementing
a "global singleton" class.


Carl Banks




More information about the Python-list mailing list