Inserting class namespace into method scope

Ben Finney ben+python at benfinney.id.au
Sun Nov 21 02:33:09 CET 2010


Steven D'Aprano <steve at REMOVE-THIS-cybersource.com.au> writes:

> I have a bunch of related functions and objects which are private to a
> module, with a single public function that acts as the API to those
> functions. I'd like to have these private functions in a namespace,
> separate from the rest of the module. Ignore the fact that they are
> private functions -- I can deal with that by the usual naming
> convention. Focus on the "separate namespace" aspect.
>
> What I want is the ability to write this:
>
> create Namespace:
>     def function(x):
>         return x
>
>     def func(y):
>         return function("spam") + "'n'" + y
>
>     dispatch = {1: func, 2: function}
>
>     def another_func(z):
>         return len(dispatch[2](z))

Can you make it concrete, by naming the namespace something meaningful
or arbitrary? It's as though you wanted to discuss a function, and named
it “function”. (Oh, you did that too :-)

I'll assume an example of a namespace for the storage backends of a
library, and that you want a namespace of ‘storage’. If you can provide
the actual use case that presents this problem to you, that would be
best.

Running with my contrived example, I take your option (2) below: use a
private module as a private namespace. In the file ‘_storage’:

    def backend_foo(x):
        return x

    def backend_bar(x):
        return backend_foo("spam") + "'n'" + x

    dispatch = {1: backend_bar, 2: backend_foo}

> func("eggs")  # raises NameError
> Namespace.func("eggs")  # returns "spam'n'eggs"
>
> Namespace.dispatch[1]("cheese")  # returns "spam'n'cheese"

    import _storage
    backend_bar("eggs")   # raises NameError
    _storage.backend_bar("eggs")   # returns "spam'n'eggs"

    _storage.dispatch[1]("cheese")  # returns "spam'n'cheese"

> (2) Place them in a separate module, and import the module, similar to
> the way that the os module imports path. This is certainly possible,
> and it works well, but it splits code into two files when it should be
> in one.

Why should it be in one? If a separate module works well, there needs to
be a good reason not to do it.

> It pollutes the module namespace, and Guido has recently expressed
> mild objection to new code doing what os does. Or at least he
> suggested that we shouldn't *encourage* doing what os does.

The single-leading-underscore naming convention makes it clear that the
module is a private implementation detail, and signals to the reader
that the module is not advisable for import except as part of that
implementation. That refutes the charge of polluting the module
namespace.

As for Guido's opinion on the matter, for whatever it's worth, those
interested are invited to read recent ‘python-dev’ discussions on APIs
<URL:http://mail.python.org/pipermail/python-dev/2010-November/105703.html>.
In short, I think he agrees with my position above.

> (3) Redesign my module to use a full package structure, and place the 
> functions in a separate module in the package. It's overkill to have a 
> package for just two namespaces (modules).

I disagree strongly. Two modules is not too few for a package; it
certainly isn't “overkill”. Packages are quite lightweight for what they
do. If they solve a problem well, I don't see why to discard them
without a better reason.


For all the other options you enumerated I am in agreement with your
position.

Thanks for making it more concrete so we know what problem we're
supposed to be grappling.

-- 
 \      “Nothing is more sacred than the facts.” —Sam Harris, _The End |
  `\                                                   of Faith_, 2004 |
_o__)                                                                  |
Ben Finney



More information about the Python-list mailing list