How to organise classes and modules

bruno at modulix onurb at xiludom.gro
Mon May 15 07:55:02 EDT 2006


Alex wrote:
> Hi, this is my first mail to the list so please correct me if Ive done
> anything wrong.
> 
> What Im trying to figure out is a good way to organise my code. One
> class per .py file is a system I like, keeps stuff apart. If I do
> that, I usually name the .py file to the same as the class in it.

First point is that Python doesn't force you to put everything in
classes - if you just need a function, well, make it a function !-)

Also, the common pattern is to put closely related
classes/functions/constants in a same module, and closely related
modules in the same package. Since Python uses a "one file == one
module" scheme, the Javaish "one class per file" idiom leads to overly
complicated imports. And the most common naming scheme for modules is
'alllowercase'.



> File: Foo.py
> ***********************
> class Foo:
>     def __init__(self):
>          pass
>     def bar(self):
>          print 'hello world'
> 
> ************************
> 
> Now, in my other module, I want to include this class. I tried these two
> ways:
> 
>>>> import Foo
>>>> Foo.Foo.bar()
>
> Traceback (most recent call last):
>  File "<stdin>", line 1, in ?
> TypeError: unbound method bar() must be called with Foo instance as
> first argument (got nothing instead)
> 
> Some unbound method error. Have I missunderstood something 

Yes:
1/ you usually need to instanciate the class to call an instance method
1/ in this case, bar doesn't need to be a method, since it doesn't
depend on the instance it's called on - a plain old function would be a
better fit.

> or am I on
> the right track here?
> 
> I did this to, almost the same thing:
> 
>>>> from Foo import Foo
>>>> Foo.bar()
> 
> Traceback (most recent call last):
>  File "<stdin>", line 1, in ?
> TypeError: unbound method bar() must be called with Foo instance as
> first argument (got nothing instead)
> 
> One thing that I tried that worked ok was this:
> 
>>>> import Foo
>>>> instance=Foo.Foo()
>>>> instance.bar()
> 
> hello world
> 
> But in my opinion, this is very ugly.

Nope, it's just OO at work.

> Especially if the class names
> are long, like my module/class TileDataBaseManager. But is this the
> "right" way in python?

If you want to import a class from a module and create an instance of
that class, yes.

> Another (ugly) way that Ive considered is the following. Break it out
> of the class,

Which would be a sensible thing to do given the current implementation
of bar().

> save the functions in a file alone,

Nothing prevent you from putting many functions in a same module, you
know...

> import the file

s/file/module/

> and
> treat it like a class:

???

> File: Foo2.py
> ***********************
> def bar(self):
>     print 'hello world'
> 
> ************************
> 
>>>> import Foo2
>>>> Foo2.bar()
> 
> hello world

You don't "treat it like a class", you're just using the normal
namespace resolution mechanism. Modules are namespaces, classes are
namespaces, objects (class instances) are namespaces, and the dot is the
 lookup operator (ie : somenamespacename.somename means 'retrieve what's
actually bound to name 'somename' in namespace 'somenamespacename').

> Very clean from the outside. I would like something like this. But,
> here, I loose the __init__ function. 

Which in the given implementation is just doing nothing.

Ok, I understand that this is just example code. The rule here is:
- if you need per-instance state management, use a class (that you of
course need to instanciate - else you can't have per-instance state !-)
- if you don't need per-instance state management, use a plain function.

> I have to call it manually that
> is, which s not good. Also, maybe the biggest drawback, its no longer
> in a class.

def MyFunc():
  pass

print MyFunc.__class__.__name__

Python function's are instances of the function class.

> Maybe its not that important in python but from what Ive
> learned (in c++) object orientation is something to strive for.

print "object orientation".find("class")

Being OO doesn't mean using classes. <troll>And FWIW, there quite enough
procedural Java code around to prove that using classes doesn't mean
doing OO !-) </troll>

> So, to sum it up, I have one class in one file, both with the same
> name. How do I store/import/handle it in a nice, clean and python-like
> manner?

Quit the Javaish "one-class-per-file" idiom, don't bother using classes
when plain old function will do, and you'll be on track...

FWIW, Python's standard lib is open-source, so why not have a look at
the source code to see how it is organized ?

HTH
-- 
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'onurb at xiludom.gro'.split('@')])"



More information about the Python-list mailing list