Encapsulation in Python

Rick Johnson rantingrickjohnson at gmail.com
Mon Mar 14 13:32:50 EDT 2016


On Sunday, March 13, 2016 at 5:11:50 AM UTC-5, Steven D'Aprano wrote:
> On Sun, 13 Mar 2016 03:44 am, Ian Kelly wrote:
> 
> > On Fri, Mar 11, 2016 at 7:39 PM, Rick Johnson
> > <rantingrickjohnson at gmail.com> wrote:
> >> At run-time, i don't care how large a "module namespace" may be.
> >> Sometimes a module namespace will be small, with only a few
> >> exposed symbols, but sometimes, a module namespace will expose
> >> thousands of symbols.
> > 
> > Thousands, really? What system do you use to ensure that symbols
> > don't accidentally collide with one another? Because, you know,
> > Python won't check this for you even within a single file, unlike
> > say C++ which does allow splitting namespaces across multiple
> > files. A linter might, but not at runtime, and I don't expect it
> > will be smart enough to notice if the definitions are in different
> > files.
> 
> I would hate to use an API with "thousands" of symbols in a single
> namespace. I find `os` difficult enough, and it has less than a
> quarter thousand:
> 
> The decimal module is, in my opinion, about as big as a module
> should ever get before it becomes too unwieldy to maintain, and it
> has less than a hundred symbols:
> 
> While it is true that the Zen says "Flat is better than nested", it
> does also say Namespaces are one honking great idea -- let's do more
> of those! so at the point that your namespace has more symbols than
> can be managed by the merely mortal, then it's well past time to
> split some of them off into separate namespaces.

But exactly where, and exactly how to drawn those lines, is
not always obvious. Splitting a large module, of similar
functionality, into smaller modules, can make the interface
confusing. Consider the following "large sized modules".

# BEGIN INTERACTIVE SESSION
PY> import OpenGL.GL
PY> import OpenGL.GLU
PY> import OpenGL.GLX
PY> import OpenGL.GLUT
PY> import OpenGL.GLE
PY> len(dir(OpenGL.GL))
3656
PY> len(dir(OpenGL.GLU))
250
PY> len(dir(OpenGL.GLX))
390
PY> len(dir(OpenGL.GLUT))
394
PY> len(dir(OpenGL.GLE))
64
PY> import Tkinter as tk
PY> len(dir(tk))
199
PY> root = tk.Tk()
PY> f = tk.Frame(root)
PY> len(dir(f))
200
# END INTERACTIVE SESSION

Ignoring Tkinter, which is a gawd awful mess, how would you
re-organize the 3,656 symbols in OpenGL.GL into smaller
modules, without dividing them up along some random or 
arbitrary lines? 

> [...]
> >> But option two is no better, because once we cut and paste
> >> portions of the code into satellite files, we lose the ability to
> >> "easily share state". Then we're forced to start "hacking at the
> >> weeds" with import contortions and monkey patches, all the while,
> >> fearing the dreaded circular import. NO, THIS IS INSANITY! WHAT
> >> WE NEED IS AN OPTION 3!
> 
> What we actually need is a way to have less shared state. If you
> have so much shared state that you cannot manage it in a single
> module, you have a problem no matter what you do.

You're missing my point. I can manage the *STATE* just fine
in a single module, actually, managing *STATE* in the same
module is very easy, regardless of how many lines are in
the file. No, it is not state that becomes unwieldy, it is
*EDITING* that becomes unwieldy. I break large source files
into small source files, simply so i don't go insane when
trying to edit them.





More information about the Python-list mailing list