views:

553

answers:

1

I am confused how directory name, file name and class name all work together.

This is what I have at the moment

  app.py
  database/
     client.py
     staff.py
     order.py

inside client.py I have a single class called client. This class acts as the database model (MVC), the same with my other files (staff.py has a class called staff, order.py - class - order)

Then in app.py I do:

  from database import client as model
  c = model.client()

and then I get confused. In an ideal world this is what I want to do:

1: keep my database model classes in separate files in their own directory.

2: use them like this:

  c = model.client()
  o = model.order()
  s = model.staff()

the only way I can see to do this is to put all my classes in a single file called model.py and save this at the root?

I'm sure I am missing something very basic here.

+4  A: 

Python has two basic ways of importing content. Modules and Packages.


A module is simply a python file on the include path: order.py

If order.py defines a class named foo, then access to that class could be had by:

import order
o = order.foo()

In order to use the syntax from the orignial question, you would need to ensure that your model.py file has the following attributes: [client, staff, order]

However, that typically means placing them in a single file. Which is what you are trying to avoid.


A package is a directory with an __init.py** inside of it. The init.py initializes the package (ie. it is run on first import), and you can have either modules or sub-packages within that directory.

model
    __init__.py
    client.py
    staff.py
    order.py

That way, to access any of the sub modules, you would simply say:

import model.client

However, that is simply importing the module. It is not importing any of the attributes of the module. So in order to access a class inside the module, you would need to specify it:

import model.client
o = model.client.clientclass()

This is a bit tedious, but very well organized.


Best of both (where performance isn't a big deal):

If you type the following code in __init.py**:

from .client import clientclass as client
from .staff import staffclass as staff
from .order import orderclass as order

Then you have auto-loaded all of your classes, and they can be accessed as:

import model
c = model.client()
s = model.staff()
o = model.order()


In the end, it may be more simple to stick with the non-magical way to do it:

import model.client
o = model.client.clientclass()

--Gahooa

gahooa
Nice answer. Why would the performance be reduced?
monk.e.boy
another question: does the verbose way [o = model.client.clientclass()] leak implementation details into the code? Say during refactoring you decide to move a class (e.g. clientclass) into its own file, you need to change the hundreds of lines where you make a new clientclass. (I'm out of chars..)
monk.e.boy
@monk.e.boy: Performance is reduced because all of the files are imported even if you only need one. If it is a long running process, or a simple program, no problem. But if it is to be loaded a lot, it can have an impact.
gahooa
@monk.e.boy: Implementation details should (IMO) be at the class level, not the module level. In other words, implementers should know the public class names at some point.
gahooa