Style for modules with lots of constants

Paul McGuire ptmcg at austin.rr._bogus_.com
Wed Nov 1 11:26:31 EST 2006


"Neil Cerutti" <horpner at yahoo.com> wrote in message 
news:slrnekhbru.1as.horpner at FIAD06.norwich.edu...
> The Glk API (which I'm implementing in native Python code)
> defines 120 or so constants that users must use. The constants
> already have fairly long names, e.g., gestalt_Version,
> evtype_Timer, keycode_PageDown.
>
> Calls to Glk functions are thus ugly and tedious.
>
>    scriptref = glk.fileref_create_by_prompt(
>            glk.fileusage_Transcript | glk.fileusage_TextMode,
>            glk.filemode_WriteAppend, 0)
>
> Please give me some good style advice for this situation.
>
> I know some modules are designed to be used as 'from XXX import
> *'. Since the Glk API is heavily influenced by its inception in
> C this might not be a huge problem. All the functions in the API
> have glk_ prepended, since C has no namespaces. I think it makes
> sense to stick the glk_'s back on the functions and instruct
> users to 'from Glk import *', but I know it doesn't conform with
> Python practice, and Python has plenty of modules that were
> originally designed in C, but don't insist on polluting the
> global namespace.
>

Neil -

I recently had to add some new constants to pyparsing, representing LEFT and 
RIGHT, but I didn't want to define such generic and 
likely-to-collide-with-user-code variable names.

I settled on defining my own flavor of the Bag class, which I named 
Constants since it is there specifically to define constants (although it 
does nothing to enforce the "constant-ness" of the values).

class Constants(object)
    pass

(I guess value immutability could probably be implemented using clever 
implementations of __setattr__ and such, but is it really worth the 
bother?).

Then I defined the context for my LEFT and RIGHT constants, which are being 
created to specify operator associativity, and then my constant fields as 
attributes of that object:

opAssoc = Constants(object)
opAssoc.RIGHT = 0
opAssoc.LEFT = 1

In client modules (that is, those that import your library) that don't like 
"from pyparsing import *", they can just add opAssoc to the list of imported 
names (as in "from pyparsing import opAssoc"), and all of the related 
constant definitions come along for the ride.

In your example, this would look something like:

fileusage = Constants()
fileusage.Transcript = 1
fileusage.TextMode = 2

filemode = Constants()
filemode.Read = 1
filemode.Write = 2
filemode.Append = 4
filemode.WriteAppend = filemode.Write | filemode.Append

and so on.  In the client modules they would simply enter "from glk import 
fileusage, filemode".  Or if they just "import glk", the references to the 
constants look like "glk.filemode.Append", "flk.fileusage.TextMode", etc., 
and those garish and unsightly '_' separators are reduced to svelte little 
'.'s.

I think this is a reasonable compromise in avoiding namespace pollution, 
without inflicting unseemly text entry overhead on your module clients.

-- Paul





More information about the Python-list mailing list