PyWart: Module access syntax

Rick Johnson rantingrickjohnson at gmail.com
Mon Jan 14 06:22:57 CET 2013


On Saturday, January 12, 2013 12:45:03 AM UTC-6, Steven D'Aprano wrote:
> On Fri, 11 Jan 2013 20:34:20 -0800, Rick Johnson wrote:
> > [...]
> 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?

Since "path" is an identifier in the module "os" that points to a system specific module (which is loaded at run-time), you would access os.path just as you do today; using the dot. No changes here. Next!

> If I do this:
> 
> import math
> import string
> math.string = string
>  
> is that legal, or do I have to write "math:string = string"?

No. You are assigning the module "string" to a member variable of the module "math" so you use the dot. No changes here. Next!

> Suppose I do this:

*rolls-eyes*

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

...first allow me to remove all the cruft so you can ask this next iteration of the _same_ hypothetical question succinctly.

if some_condition:
    math.string = ""
else
    math.string = string

> How do I access the string member?

You access the member variable named "string" (that points to the "string module") as you would ANY _member_,  using the dot. Next!

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

EARTH TO STEVEN: You are sadly misunderstanding my suggested syntax and frankly making a complete fool of yourself. I cannot allow this to go on any longer.

> That would suck *and* blow at the same time. 

Yes it would, but that's only _IF_ my suggested syntax works in the backwards way you suggest. Lucky for us, i'm designing this feature.

> 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?

I said it before and i'll say it again: If you don't know if your calls are accessing module space or object space (be it instanced object or static object), then you are sadly informed and shooting from the hip -- you're going to shoot your toes off! But that is not the worst part, no. The worst part is that by using only the dot, your code is superfluously obfuscated. That is a crime to me. A crime punishable by the syntax error. I condemn you to tortuous syntax errors until you change your rebellious ways.

> Now, suppose I then do this:
> 
> class Blob: pass
> 
> blob = Blob()
> blob.math = math  # or should that be blob:math ?

Oh lord. 

Has anyone noticed that every one of these hypotheticals is presenting the very same question using different circumstances. Do you think 1+1 will sometimes equal 2 Steven?

You are missing the point of this syntax. The colon is to access MODULE NAMESPACE. The dot is to access MODULE MEMBERS. A module CAN BE another module's MEMBER. 

You are also unable to grasp this simple logical fact: Once you arrive at /any/ MODULE and you start accessing MEMBERS, you will *_ALWAYS_* find members from that point downwards. 

Observe:

In module "lib:foo":
    import string
    import math
    import math as _math
    from math import ceil
    #    
    string.math = math
    string.math.var="var"


In __main__ (test 1):
    import lib:foo
    import lib:foo as foo    
    # Test 1
    print lib:foo.string.math.var -> "var"
    # Test 2
    print foo.string.math.var -> "var"
    # Test 3
    foo.string.math.ceil(.1) -> 1.0
    # Test 4:
    foo.ceil(.1) -> 1.0

> [...]
>
> > Traceback (most recent call last):
> >   File "<blah>", line 1, in <module>
> >     dlg = lib:gui:tkinter:dialogs.simpledialog()
> 
> 
> Of course it is an object. *Everything* in Python is an object. 

And i agree! ("it" being "modules" in this case)

> Modules 
> are objects. Strings are objects. Types and classes are objects.

Wait, "classes" are NOT objects. Classes are structured code that DEFINE an object. You see, this is exactly why we need to stop using the word "class" to describe an "object definition". Your ability to grasp _what_ an object definition *IS* is due to poor terminology. 

> None is 
> an object. Metaclasses are objects. Properties are objects. Exceptions 
> are objects. Have I made it clear yet?

Yes, but your point is invalid. I was comparing a module to an object. And even though EVERYTHING in Python is technically an object, you should have inferred the meaning of my comparison, but alas, you cannot even infer my syntax!

> > *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?

Because modules and objects are not the same and someone who is reading the source code NEEDS to know which "path members" are /modules/ and which "path members" are /objects/.  And he needs to know that very important information WITHOUT opening source files to find out. 

Look, we cannot provide /every/ possible detail about an object via syntax alone, HOWEVER, here we have a golden opportunity to provide one more piece of that puzzle without any negative trade-offs. Oh yes, *rolls-eyes*, the programmer will need to be sure he places a colon between modules. Which means a programmer will need to know which path members are modules and which are objects... But are you actually telling me that you're unable to remember which objects you are accessing are modules and which are members? And if you cannot, you /could/ resolve the conflict much easier yourself than a reader can resolve the conflict -- Why? because you are closer to the code structure. And why are you closer to the code structure? BECAUSE YOU WROTE IT!

> 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.

 WRONG! What you need to do is to read my proposal again and try to comprehend it before going off on these nonsensical tirades.
 
> 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.

Are you serious? You are pissing and moaning about keeping up with TWO types and any /real/ programmer has to corral many *many* types in one program? 

We not only have to care if a member is a module or not Steven, we have to care whether a member is a float, or an integer, or a string, or a tuple, or a complex, or an iterator, or a range, or a list, or a set, or a frozenset, or a dict, or a ordereddict or a function, or an object (as in: "user defined object") or blah, blah, blah.

Your argument is nothing more than BS. You thought you could fool me with sleight of hand. Nice try, but you lose. Better luck next time. 

py> currentTroll.vanquish()
py> trollist.next()



More information about the Python-list mailing list