PyWart: Module access syntax

Steven D'Aprano steve+comp.lang.python at
Sat Jan 12 07:45:03 CET 2013

On Fri, 11 Jan 2013 20:34:20 -0800, Rick Johnson wrote:

>> >  import lib:gui:tkinter:dialogs.SimpleDialog as Blah
>> Which names are packages, modules, classes, methods, functions, or
>> other objects?
>> Why do you have lib:gui but dialogs.SimpleDialog? Is the rule "classes
>> should always be preceded by a dot?"
> No the rules are:
>     * "Colon" must be used to access a "module" (or a package).
>     * "Dot" must be used to access a "module member".

So what do you do for, say, os.path? According to the first rule, you 
must write it as os:path because path is a module; according to the 
second rule, you must write it as os.path because path is a member of os. 
So which rule wins?

If I do this:

import math
import string
math.string = string

is that legal, or do I have to write "math:string = string"?

Suppose I do this:

import random
if random.random() < 0.5:
    math.string = "NOBODY expects the Spanish Inquisition!"
    math.string = string  # assuming this actually is allowed

How do I access the string member?

    print math.string  # only works if string is a str object
except SomeException:
    print math:string  # only works if string is a module object

That would suck *and* blow at the same time. I don't need to know the 
type of any other member object in order to look it up, why should I have 
to care whether it is a module?

Now, suppose I then do this:

class Blob: pass

blob = Blob()
blob.math = math  # or should that be blob:math ?

Now do I have to write this?


(assuming that math:string is a module, not a str object).

> It's simple: MODULES&PACKAGES use colon, MODULE MEMBERS use dot. How
> many times must i explain these simple rules?

At the time I asked the question, you hadn't explained it *at all*.

> This syntax does not help the programmer much. Well, it can be
> beneficial to the programmer if he gets a *PathError* because he
> foolishly tried to instance a module named "simpledialog" when he
> actually meant to instance the object "simpledialog.SimpleDialog".
> (notice i did not use the word class!)

"Instance" is a noun. The verb you are looking for is "instantiate".

> Traceback (most recent call last):
>   File "<blah>", line 1, in <module>
>     dlg = lib:gui:tkinter:dialogs.simpledialog()
> PathError: name 'simpledialog' is a module NOT a object!

Of course it is an object. *Everything* in Python is an object. Modules 
are objects. Strings are objects. Types and classes are objects. None is 
an object. Metaclasses are objects. Properties are objects. Exceptions 
are objects. Have I made it clear yet?

> *The problem:*
> ... is readability. The current dot syntax used ubiquitously in paths is
> not conveying the proper information to the reader, and in-fact
> obfuscating the code.

So you say. I think you are caring too much about the type of members and 
not enough about what interface they provide. Why do you care if I grab 
module.my_singleton_object and replace my_singleton_object with a module?

Modules are singletons in Python, in the sense that every[1] time you 
import a module you get the same object. Using modules as members for 
their singleton properties, not for their importability, is a common 
technique. With your proposal, I need to know whether a member is a 
module, or any other type, before I can access it. That is a really 
shitty design. Instead of having one syntax for *all* attribute access, 
now you have two, and we have to care whether a member is a module or 
not, which we never did before.

Worse, you couple the syntax to implementation: if I use a module as a 
singleton, I need to use one syntax; if I use a custom type as a 
singleton, I have to use different syntax. Whichever choice I make 
*today*, if the implementation changes, the required syntax changes and 
my code will break.

[1] Well, almost. There are ways to accidentally or deliberately confuse 
the import machinery.


More information about the Python-list mailing list