Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #36605 > unrolled thread

PyWart: Module access syntax

Started byRick Johnson <rantingrickjohnson@gmail.com>
First post2013-01-10 22:01 -0800
Last post2013-01-12 12:16 +0000
Articles 20 on this page of 24 — 8 participants

Back to article view | Back to comp.lang.python


Contents

  PyWart: Module access syntax Rick Johnson <rantingrickjohnson@gmail.com> - 2013-01-10 22:01 -0800
    Re: PyWart: Module access syntax Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-01-11 16:02 +0000
      Re: PyWart: Module access syntax Rick Johnson <rantingrickjohnson@gmail.com> - 2013-01-11 20:34 -0800
        Re: PyWart: Module access syntax Chris Angelico <rosuav@gmail.com> - 2013-01-12 15:40 +1100
          Re: PyWart: Module access syntax Rick Johnson <rantingrickjohnson@gmail.com> - 2013-01-11 21:46 -0800
            Re: PyWart: Module access syntax Chris Angelico <rosuav@gmail.com> - 2013-01-12 16:59 +1100
            Re: PyWart: Module access syntax Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-01-12 06:53 +0000
          Re: PyWart: Module access syntax Rick Johnson <rantingrickjohnson@gmail.com> - 2013-01-11 21:46 -0800
          Re: PyWart: Module access syntax 88888 Dihedral <dihedral88888@googlemail.com> - 2013-01-12 16:02 -0800
          Re: PyWart: Module access syntax 88888 Dihedral <dihedral88888@googlemail.com> - 2013-01-12 16:02 -0800
        Re: PyWart: Module access syntax Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-01-12 06:45 +0000
          Re: PyWart: Module access syntax Rick Johnson <rantingrickjohnson@gmail.com> - 2013-01-13 21:22 -0800
            Re: PyWart: Module access syntax Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-01-14 17:34 +0000
              Re: PyWart: Module access syntax Rick Johnson <rantingrickjohnson@gmail.com> - 2013-01-14 23:07 -0800
            Re: PyWart: Module access syntax Ian Kelly <ian.g.kelly@gmail.com> - 2013-01-14 11:51 -0700
              Re: PyWart: Module access syntax Rick Johnson <rantingrickjohnson@gmail.com> - 2013-01-14 23:49 -0800
                Re: PyWart: Module access syntax Chris Angelico <rosuav@gmail.com> - 2013-01-15 19:08 +1100
              Re: PyWart: Module access syntax Rick Johnson <rantingrickjohnson@gmail.com> - 2013-01-14 23:49 -0800
            Re: PyWart: Module access syntax Ian Kelly <ian.g.kelly@gmail.com> - 2013-01-14 12:04 -0700
            Re: PyWart: Module access syntax "D'Arcy J.M. Cain" <darcy@druid.net> - 2013-01-14 14:35 -0500
            Re: PyWart: Module access syntax Ian Kelly <ian.g.kelly@gmail.com> - 2013-01-14 13:38 -0700
        Re: PyWart: Module access syntax Ian Kelly <ian.g.kelly@gmail.com> - 2013-01-11 23:55 -0700
        Re: PyWart: Module access syntax alex23 <wuwei23@gmail.com> - 2013-01-11 23:36 -0800
    Re: PyWart: Module access syntax Nicholas Cole <nicholas.cole@gmail.com> - 2013-01-12 12:16 +0000

Page 1 of 2  [1] 2  Next page →


#36605 — PyWart: Module access syntax

FromRick Johnson <rantingrickjohnson@gmail.com>
Date2013-01-10 22:01 -0800
SubjectPyWart: Module access syntax
Message-ID<8e9b2b0e-1c34-46cc-80c6-57fbb5fd756c@googlegroups.com>
Python's module/package access uses dot notation. 

  mod1.mod2.mod3.modN

Like many warts of the language, this wart is not so apparent when first learning the language. The dot seems innocently sufficient, however, in truth it is woefully inadequate! Observe:

 name1.name2.name3.name4.name5

Can you tell me which names are modules, which are classes, and which are methods/functions? Wait, i know the argument you'll use:

  """I can decipher from spelling! Modules use all lowercase, classes use initial uppercase, and methods use words_sep_by_underscore. I'm so smart!"""

Indeed. But that's only *_IF_* everybody used the same style guide. And as we know many people don't follow the style guide (not to mention the style guide has issues!) And since style is NOT enforced, we suffer the unintuitive syntax nightmare! The solution is obvious by using proper syntax. 

 import lib:gui:tkinter:dialogs.SimpleDialog as Blah

You /could/ use two colons:
 
 import lib::gui::tkinter::dialogs.SimpleDialog as Blah

...and i think this syntax does help to separate the identifiers more clearly, but since these imports can be quite long, i prefer the single colon myself.

[toc] | [next] | [standalone]


#36630

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2013-01-11 16:02 +0000
Message-ID<50f03799$0$30003$c3e8da3$5496439d@news.astraweb.com>
In reply to#36605
On Thu, 10 Jan 2013 22:01:37 -0800, Rick Johnson wrote:

> Python's module/package access uses dot notation.
> 
>   mod1.mod2.mod3.modN
> 
> Like many warts of the language, this wart is not so apparent when first
> learning the language. The dot seems innocently sufficient, however, in
> truth it is woefully inadequate! Observe:
> 
>  name1.name2.name3.name4.name5
> 
> Can you tell me which names are modules, which are classes, and which
> are methods/functions? Wait, i know the argument you'll use:
> 
>   """I can decipher from spelling! Modules use all lowercase, classes
>   use initial uppercase, and methods use words_sep_by_underscore. I'm so
>   smart!"""

Wrong. My answer is... 

Who cares? Why do you care which names are modules, classes, etc? This is 
Python, and duck-typing rules!

Today I have:

x = mylib.stuff.spam().parrot.speak()

where:

- mylib is a module
- stuff is a separate module imported into mylib
- spam is a class
- parrot a data attribute
- and speak a method. 

But then tomorrow I re-factor the code and turn:

- mylib into a package
- stuff into a module of the package
- spam into a factory function
- parrot into a property
- and speak into a dynamically generated static method created using 
__getattr__.

How do I write this new code? Exactly the same as the old code -- no 
changes are required!

x = mylib.stuff.spam().parrot.speak()

*It doesn't matter* what kind of entity each of the dotted names 
represent, so long as they have the expected interface.


> The solution is obvious by using proper syntax.

Solution to what? You can only have a solution once you have identified a 
problem. You have not identified a problem. In any case, your suggestion 
is *not* obvious.

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

Following this import:

import lib:gui

how do I access attributes of that module? 

x = lib:gui:function() perhaps? Now I have to remember which attribute 
access uses dot operator and which uses colon operator.

Does this mean there needs to four new be special methods:

__getcolonattribute__
__getcolonattr__
__setcolonattr__ 
__delcolonattr__ 

to match the regular dot operator methods

__getattribute__
__getattr__ 
__setattr__ 
__delattr__ 

? Or do you think that the Python compiler should special-case attribute 
access from modules?


> You /could/ use two colons:
>  
>  import lib::gui::tkinter::dialogs.SimpleDialog as Blah

Before thinking about the syntax, you need to think about the behaviour, 
identify what actual problem you hope to solve, and how you hope to solve 
it. Not just throw random syntax around and hope that it's "obvious".



-- 
Steven

[toc] | [prev] | [next] | [standalone]


#36665

FromRick Johnson <rantingrickjohnson@gmail.com>
Date2013-01-11 20:34 -0800
Message-ID<9b64719e-1e06-47fa-a7e6-692a3dd360d0@googlegroups.com>
In reply to#36630
On Friday, 1-11-2013 10:02:34 AM, Steven D'Aprano wrote:
> Solution to what? You can only have a solution once you have identified a 
> problem. You have not identified a problem. In any case, your suggestion 
> is *not* obvious.

The problem is that by using the dot ubiquitously we are obfuscating the path to an identifier. 

> >  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".
    
In the line "lib:gui:tkinter:dialogs.SimpleDialog", "lib", "gui", "tkinter", and "dialogs" are all packages (or modules: same thing as far as paths are concerned). "SimpleDialog" however is a class, who's identifier is a member of the module "lib:gui:tkinter:dialogs". 

> Following this import:
> 
> import lib:gui
> 
> how do I access attributes of that module? 
> 
> x = lib:gui:function() perhaps? Now I have to remember which attribute 
> access uses dot operator and which uses colon operator.

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

If you don't know which names are modules and which names are members then how could a programmer possibly use the API in an intelligent way Steven? 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!)

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!

But that is not the reason for this syntax Steven, it is just a pleasant side effect.

> Does this mean there needs to four new be special methods:
> 
> __getcolonattribute__
> __getcolonattr__
> __setcolonattr__ 
> __delcolonattr__ 

Gawd no. getattr, setattr, and delattr will remain unchanged. The only change is how a /path/ to an identifier is "formed".

> to match the regular dot operator methods
> 
> __getattribute__
> __getattr__ 
> __setattr__ 
> __delattr__ 
> 
> ? Or do you think that the Python compiler should special-case attribute 
> access from modules?

There is no "special casing" needed. Python could happily replace all colons in a path with dots and interpret the path internally just as it does today.

> Before thinking about the syntax, you need to think about the behaviour, 
> identify what actual problem you hope to solve, and how you hope to solve 
> it. Not just throw random syntax around and hope that it's "obvious".

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

*Method to solve the problem:*
... by introducing a new syntax that requires all module access to use the colon and all module members to use the dot.

*The syntax:*
... is perfect. Of course we could argue over /which/ char to use, but no matter which char prevails, we are gaining explicitness at zero overhead to the programmer because we are replacing one single char(dot) for one single  char(colon). The maintainer is the real winner. This is a win-win all around. 

[toc] | [prev] | [next] | [standalone]


#36667

FromChris Angelico <rosuav@gmail.com>
Date2013-01-12 15:40 +1100
Message-ID<mailman.425.1357965645.2939.python-list@python.org>
In reply to#36665
On Sat, Jan 12, 2013 at 3:34 PM, Rick Johnson
<rantingrickjohnson@gmail.com> wrote:
> *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.

Please explain how this is a problem. As Steven said, there is NO
useful difference. I don't *care* whether it's a package, a module, or
whatever. Module with class with static member? Fine. Package with
module with class? Also fine. Imported special object that uses dunder
methods to simulate either of the above? What's it matter to me, as
long as I get my final result!

Syntactic salt is seldom helpful.

ChrisA

[toc] | [prev] | [next] | [standalone]


#36676

FromRick Johnson <rantingrickjohnson@gmail.com>
Date2013-01-11 21:46 -0800
Message-ID<73ecfe98-997a-49bb-a4d7-4fbfbde4277a@googlegroups.com>
In reply to#36667
On Friday, January 11, 2013 10:40:36 PM UTC-6, Chris Angelico wrote:
> On Sat, Jan 12, 2013 at 3:34 PM, Rick Johnson

> > *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.
> 
> Please explain how this is a problem. 


What is this importing?

   "import lib.gui.simpledialog"
 
...is that the "simpledialog module" or "SimpleDialog object"? Since naming conventions are not ENFORCED, we can NEVER be sure if an identifier is a object or module. And since object definitions (aka: classes) are often placed into a module with the same name, how are we to know? Why should we be forced to open source files to find out a small detail that proper syntax can easily provide?

This is a matter of READABILITY, Christopher. It's one or the other (or the status quo):

1. Enforce naming conventions.
2. Enforce path syntax.
3. Continue to obfuscate code.

The choice is yours.

[toc] | [prev] | [next] | [standalone]


#36678

FromChris Angelico <rosuav@gmail.com>
Date2013-01-12 16:59 +1100
Message-ID<mailman.432.1357970374.2939.python-list@python.org>
In reply to#36676
On Sat, Jan 12, 2013 at 4:46 PM, Rick Johnson
<rantingrickjohnson@gmail.com> wrote:
> This is a matter of READABILITY, Christopher. It's one or the other (or the status quo):
>
> 1. Enforce naming conventions.
> 2. Enforce path syntax.
> 3. Continue to duck type, like Python is good at.
>
> The choice is yours.

FTFY.

ChrisA

[toc] | [prev] | [next] | [standalone]


#36682

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2013-01-12 06:53 +0000
Message-ID<50f10866$0$30003$c3e8da3$5496439d@news.astraweb.com>
In reply to#36676
On Fri, 11 Jan 2013 21:46:36 -0800, Rick Johnson wrote:

> On Friday, January 11, 2013 10:40:36 PM UTC-6, Chris Angelico wrote:
>> On Sat, Jan 12, 2013 at 3:34 PM, Rick Johnson
> 
>> > *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.
>> 
>> Please explain how this is a problem.
> 
> 
> What is this importing?
> 
>    "import lib.gui.simpledialog"
>  
> ...is that the "simpledialog module" or "SimpleDialog object"? 

It has to be the first, because:

- you can't import members of modules directly using dot syntax

  ("import math.cos" will fail)

- and it can't be SimpleDialog, because Python is case-sensitive and you 
wrote simpledialog.


But ignoring the import, and just looking at the dotted name:

lib.gui.simpledialog

who cares what simpledialog happens to be? So long as you know the 
expected interface (say, "it's a callable object that takes three 
arguments"), you can use it the same way whether it is a function, a 
method, a class or something else. The implementation could change, and 
you need not care.

If you actually do care what the type of simpledialog is, you can find 
out easily:

type(lib.gui.simpledialog)



-- 
Steven

[toc] | [prev] | [next] | [standalone]


#36677

FromRick Johnson <rantingrickjohnson@gmail.com>
Date2013-01-11 21:46 -0800
Message-ID<mailman.431.1357970216.2939.python-list@python.org>
In reply to#36667
On Friday, January 11, 2013 10:40:36 PM UTC-6, Chris Angelico wrote:
> On Sat, Jan 12, 2013 at 3:34 PM, Rick Johnson

> > *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.
> 
> Please explain how this is a problem. 


What is this importing?

   "import lib.gui.simpledialog"
 
...is that the "simpledialog module" or "SimpleDialog object"? Since naming conventions are not ENFORCED, we can NEVER be sure if an identifier is a object or module. And since object definitions (aka: classes) are often placed into a module with the same name, how are we to know? Why should we be forced to open source files to find out a small detail that proper syntax can easily provide?

This is a matter of READABILITY, Christopher. It's one or the other (or the status quo):

1. Enforce naming conventions.
2. Enforce path syntax.
3. Continue to obfuscate code.

The choice is yours.

[toc] | [prev] | [next] | [standalone]


#36716

From88888 Dihedral <dihedral88888@googlemail.com>
Date2013-01-12 16:02 -0800
Message-ID<78f555ef-7c2e-4102-8a6a-993a8bbae058@googlegroups.com>
In reply to#36667
Chris Angelico於 2013年1月12日星期六UTC+8下午12時40分36秒寫道:
> On Sat, Jan 12, 2013 at 3:34 PM, Rick Johnson
> 
> <rantingrickjohnson@gmail.com> wrote:
> 
> > *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.
> 
> 
> 
> Please explain how this is a problem. As Steven said, there is NO
> 
> useful difference. I don't *care* whether it's a package, a module, or
> 
> whatever. Module with class with static member? Fine. Package with
> 
> module with class? Also fine. Imported special object that uses dunder
> 
> methods to simulate either of the above? What's it matter to me, as
> 
> long as I get my final result!
> 
> 
> 
> Syntactic salt is seldom helpful.
> 
> 
> 
> ChrisA
This is somewhat like the following problem.

Do we have to argue with people about the tastes 
of dishes in different restaurants ?

Of course, I do because I love to enjoy fine dishes.


[toc] | [prev] | [next] | [standalone]


#36717

From88888 Dihedral <dihedral88888@googlemail.com>
Date2013-01-12 16:02 -0800
Message-ID<mailman.457.1358035357.2939.python-list@python.org>
In reply to#36667
Chris Angelico於 2013年1月12日星期六UTC+8下午12時40分36秒寫道:
> On Sat, Jan 12, 2013 at 3:34 PM, Rick Johnson
> 
> <rantingrickjohnson@gmail.com> wrote:
> 
> > *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.
> 
> 
> 
> Please explain how this is a problem. As Steven said, there is NO
> 
> useful difference. I don't *care* whether it's a package, a module, or
> 
> whatever. Module with class with static member? Fine. Package with
> 
> module with class? Also fine. Imported special object that uses dunder
> 
> methods to simulate either of the above? What's it matter to me, as
> 
> long as I get my final result!
> 
> 
> 
> Syntactic salt is seldom helpful.
> 
> 
> 
> ChrisA
This is somewhat like the following problem.

Do we have to argue with people about the tastes 
of dishes in different restaurants ?

Of course, I do because I love to enjoy fine dishes.


[toc] | [prev] | [next] | [standalone]


#36681

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2013-01-12 06:45 +0000
Message-ID<50f1066f$0$30003$c3e8da3$5496439d@news.astraweb.com>
In reply to#36665
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!"
else:
    math.string = string  # assuming this actually is allowed


How do I access the string member?

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


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?

blob.math:string.letters

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


-- 
Steven

[toc] | [prev] | [next] | [standalone]


#36768

FromRick Johnson <rantingrickjohnson@gmail.com>
Date2013-01-13 21:22 -0800
Message-ID<af1ad595-4ee6-4b9f-86fb-845c025fb417@googlegroups.com>
In reply to#36681
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()

[toc] | [prev] | [next] | [standalone]


#36803

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2013-01-14 17:34 +0000
Message-ID<50f441c0$0$30003$c3e8da3$5496439d@news.astraweb.com>
In reply to#36768
On Sun, 13 Jan 2013 21:22:57 -0800, Rick Johnson wrote:

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

Here you say that os.path will not change. But later in your post, you 
say:


> 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

Since both os and path are modules, you here say that they need a colon 
between them. This contradicts the above when you say the syntax for 
os.path won't change.

If even you don't understand your own proposal, how do you expect anyone 
else to understand it?

Perhaps you should start by explaining, unambiguously and IN FULL, under 
what circumstances the programmer will need to use your : syntax.

To start:

os.path or os:path

json.scanner or json:scanner



> 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

"Sadly informed"? Dr Freud called, he wants his slip back.

Modules are objects, and there is no difference between module space and 
object space, except that Python provides a convenience syntax for 
members of the current module. Modules are instances of a class, just 
like ints, strings, lists, and everything else.


py> from types import ModuleType
py> type(ModuleType) is type(int)
True

py> hasattr(os, '__dict__')
True


[...]
> Wait, "classes" are NOT objects.

They certainly are. Classes are created at runtime, they have a type -- 
the class of a class is the metaclass. You can even customize class 
behaviour with metaclass programming.

Perhaps you are thinking about some other language, like Java, which 
fails to have first-class classes (pun intended).


-- 
Steven

[toc] | [prev] | [next] | [standalone]


#36838

FromRick Johnson <rantingrickjohnson@gmail.com>
Date2013-01-14 23:07 -0800
Message-ID<a1de337d-a2a3-4057-b613-a60ebfb5e371@googlegroups.com>
In reply to#36803
On Monday, January 14, 2013 11:34:56 AM UTC-6, Steven D'Aprano wrote:

> Since both os and path are modules, you here say that they need a colon 
> between them. This contradicts the above when you say the syntax for 
> os.path won't change.

But you forgot the rule about accessing module members with the dot :)

> If even you don't understand your own proposal, how do you expect anyone 
> else to understand it?
> 
> Perhaps you should start by explaining, unambiguously and IN FULL, under 
> what circumstances the programmer will need to use your : syntax.

I will admit i may have confused a few of you (and myself) since i overused the word "module" when i really meant "package".

pkg1:pkg2:pkgN.member1.member2.memberN

[toc] | [prev] | [next] | [standalone]


#36809

FromIan Kelly <ian.g.kelly@gmail.com>
Date2013-01-14 11:51 -0700
Message-ID<mailman.512.1358189552.2939.python-list@python.org>
In reply to#36768
On Sun, Jan 13, 2013 at 10:22 PM, Rick Johnson
<rantingrickjohnson@gmail.com> wrote:
> 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.

If you want us to understand the syntax, then you need to define
precisely what you mean by these terms.  In what situation does a
module have a dotted/coloned path without being a member of another
module?  Any time you import a.b, the import mechanism finds and loads
module b and adds it *as a member* to module a.  It follows that a
module accessible by a module path is *always* a member of another
module.  By the above rule, then it would seem that the dot would
always be used, and the colon never.

I think the distinction you are trying to make here is based upon the
submodule's actual source location on the disk.  If you have a package
folder A which contains a file B.py, then you would access that as
A:B, correct?  If on the other hand you have a module A.py or package
A/__init__.py that loads a module from some other location and then
stores it in the A module with the name "B", then that would be "A.B",
correct?

If I have that right, then the problem with this is that it breaks the
virtualization and encapsulation of Python's package structure.  When
I import os.path, I don't have to know or care how the submodule
relationship is implemented, whether it's a simple module in a package
or something more complicated.  All I need to know is that path is a
submodule of os.  What you're asking for is that I have to type either
"os.path" or "os:path" depending on an implementation detail of the
module structure, and if that implementation detail ever changes, then
my code breaks.

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

Why does anybody reading the source code need to know this?  We're
talking about simple namespaces here.  Nobody reading the source needs
to care whether those namespaces are implemented as modules or some
other type of object.  The only substantive difference between the two
is whether you can expect to be able to import them directly.  If you
need to know that, read the documentation.  If they're documented as
modules, then you can import them.  Otherwise, make no such
assumption, because even if it works now, that could change later.

If we're *not* talking about simple namespaces, then it should be very
obvious that they are not modules based upon the fact that the code
uses them in ways that modules are not normally used for.

[toc] | [prev] | [next] | [standalone]


#36841

FromRick Johnson <rantingrickjohnson@gmail.com>
Date2013-01-14 23:49 -0800
Message-ID<913c3f21-5449-4b2c-9fb5-c3520acb3a9d@googlegroups.com>
In reply to#36809
On Monday, January 14, 2013 12:51:50 PM UTC-6, Ian wrote:

> I think the distinction you are trying to make here is based upon the
> submodule's actual source location on the disk.  If you have a package
> folder A which contains a file B.py, then you would access that as
> A:B, correct?  If on the other hand you have a module A.py or package
> A/__init__.py that loads a module from some other location and then
> stores it in the A module with the name "B", then that would be "A.B",
> correct?

Yes! The colon accesses package space (the "top-level namespace" if you will). The dot accesses members. 

> If I have that right, then the problem with this is that it breaks the
> virtualization and encapsulation of Python's package structure.  When
> I import os.path, I don't have to know or care how the submodule
> relationship is implemented, whether it's a simple module in a package
> or something more complicated.  All I need to know is that path is a
> submodule of os.  

Well one the main problem with packages is that we have no rules for defining them. I think of packages as namespaces. And as such they should have public members, private members, and shared members. The author of ANY package should place the /public members/ into the __init__ file *via import* for access by the user. The user should NEVER access package sub-modules directly!

> What you're asking for is that I have to type either
> "os.path" or "os:path" depending on an implementation detail of the
> module structure, and if that implementation detail ever changes, then
> my code breaks.

You keep using os.path as an example. path should be it's OWN module living in some package, and NOT a member of os. So you would import them separately. But if insist on keeping "path" in "os", fine. Even IF os where a package, the syntax would still be the same because there is only one level of package ("os") before you get to the member "path". Do you understand?

   os.path.whatever
   
However, if "os" lived in a package named "lib" you would access via:

  lib:os.path

See, the colon designates package namespace.

But these modules are bad examples because they do not require deep nesting of packages. GUI libraries however are a great example. That is why i posted the hypothetical path:

  lib:gui:tk:dialogs.SimpleDialog

Here are few more to get a feel:

  lib:gui:tk:dialogs.MessageBox
  lib:gui:tk:dialogs.FileDlg
  lib:gui:tk.constants
  lib:gui:tk:widgets:Button
  lib:gui:tk:widgets:XXX
  
If we build consistent packages and use a consistent syntax to access them, our code will be self documenting. However, I don't think the Python devs take the subject of packages very seriously. 

For example, look at Tkinter in Py3000, we still have a single monolithic "tkinter" module with every possible widget class stuffed into it, along with ABCs, and variables classes, and outdated functions, and the kitchen sink! All they did was to move and rename the dialog and font classes and then patted themselves on the back.

This is NOT how you structure a package!  We need to use a structured package approach to tame this wild beast called Tkinter. 

Look, maybe nobody has the time to deal with this module, so if you need some help, then feel free to ask for my assistance. All Guido has to do is send me a private email and say:

""" Hello Rick! Your ideas for packaging of Tkinter are interesting, and i would like for you to send a patch over to {0} for immediate consideration. Thanks GvR """.format(destination)

But if he cannot even care enough about Python to send a single paragraph email, or he's holding a grudge because i am critical of "some" parts of the language, well then, don't be expecting any help from me! I would not bother to criticize if i did not think Python was the best base for which to build a great language.

Nobody can build a perfect language, Guido included. You give it you best shot and then you tweak and tinker as new unforeseen problems arise. Sometimes you have no choice but to break backwards compatibility. These are all necessary stepping stones in a languages evolution. This snake needs to shed an old skin so the new skin can grow.

[toc] | [prev] | [next] | [standalone]


#36843

FromChris Angelico <rosuav@gmail.com>
Date2013-01-15 19:08 +1100
Message-ID<mailman.532.1358237314.2939.python-list@python.org>
In reply to#36841
On Tue, Jan 15, 2013 at 6:49 PM, Rick Johnson
<rantingrickjohnson@gmail.com> wrote:
> Look, maybe nobody has the time to deal with this module, so if you need some help, then feel free to ask for my assistance. All Guido has to do is send me a private email and say:
>
> """ Hello Rick! Your ideas for packaging of Tkinter are interesting, and i would like for you to send a patch over to {0} for immediate consideration. Thanks GvR """.format(destination)

Python's open source. Grab the source, do it, and post! Consider
yourself preemptively invited.

I'm not kidding. You don't need to wait for Guido's invitation to do
something. Just get in there, do something, and (preferably) show an
upgrade path from "current status" to "proposed status" - which might
involve a translation script similar to 2to3 - and people WILL take
notice.

ChrisA

[toc] | [prev] | [next] | [standalone]


#36842

FromRick Johnson <rantingrickjohnson@gmail.com>
Date2013-01-14 23:49 -0800
Message-ID<mailman.531.1358236175.2939.python-list@python.org>
In reply to#36809
On Monday, January 14, 2013 12:51:50 PM UTC-6, Ian wrote:

> I think the distinction you are trying to make here is based upon the
> submodule's actual source location on the disk.  If you have a package
> folder A which contains a file B.py, then you would access that as
> A:B, correct?  If on the other hand you have a module A.py or package
> A/__init__.py that loads a module from some other location and then
> stores it in the A module with the name "B", then that would be "A.B",
> correct?

Yes! The colon accesses package space (the "top-level namespace" if you will). The dot accesses members. 

> If I have that right, then the problem with this is that it breaks the
> virtualization and encapsulation of Python's package structure.  When
> I import os.path, I don't have to know or care how the submodule
> relationship is implemented, whether it's a simple module in a package
> or something more complicated.  All I need to know is that path is a
> submodule of os.  

Well one the main problem with packages is that we have no rules for defining them. I think of packages as namespaces. And as such they should have public members, private members, and shared members. The author of ANY package should place the /public members/ into the __init__ file *via import* for access by the user. The user should NEVER access package sub-modules directly!

> What you're asking for is that I have to type either
> "os.path" or "os:path" depending on an implementation detail of the
> module structure, and if that implementation detail ever changes, then
> my code breaks.

You keep using os.path as an example. path should be it's OWN module living in some package, and NOT a member of os. So you would import them separately. But if insist on keeping "path" in "os", fine. Even IF os where a package, the syntax would still be the same because there is only one level of package ("os") before you get to the member "path". Do you understand?

   os.path.whatever
   
However, if "os" lived in a package named "lib" you would access via:

  lib:os.path

See, the colon designates package namespace.

But these modules are bad examples because they do not require deep nesting of packages. GUI libraries however are a great example. That is why i posted the hypothetical path:

  lib:gui:tk:dialogs.SimpleDialog

Here are few more to get a feel:

  lib:gui:tk:dialogs.MessageBox
  lib:gui:tk:dialogs.FileDlg
  lib:gui:tk.constants
  lib:gui:tk:widgets:Button
  lib:gui:tk:widgets:XXX
  
If we build consistent packages and use a consistent syntax to access them, our code will be self documenting. However, I don't think the Python devs take the subject of packages very seriously. 

For example, look at Tkinter in Py3000, we still have a single monolithic "tkinter" module with every possible widget class stuffed into it, along with ABCs, and variables classes, and outdated functions, and the kitchen sink! All they did was to move and rename the dialog and font classes and then patted themselves on the back.

This is NOT how you structure a package!  We need to use a structured package approach to tame this wild beast called Tkinter. 

Look, maybe nobody has the time to deal with this module, so if you need some help, then feel free to ask for my assistance. All Guido has to do is send me a private email and say:

""" Hello Rick! Your ideas for packaging of Tkinter are interesting, and i would like for you to send a patch over to {0} for immediate consideration. Thanks GvR """.format(destination)

But if he cannot even care enough about Python to send a single paragraph email, or he's holding a grudge because i am critical of "some" parts of the language, well then, don't be expecting any help from me! I would not bother to criticize if i did not think Python was the best base for which to build a great language.

Nobody can build a perfect language, Guido included. You give it you best shot and then you tweak and tinker as new unforeseen problems arise. Sometimes you have no choice but to break backwards compatibility. These are all necessary stepping stones in a languages evolution. This snake needs to shed an old skin so the new skin can grow.

[toc] | [prev] | [next] | [standalone]


#36812

FromIan Kelly <ian.g.kelly@gmail.com>
Date2013-01-14 12:04 -0700
Message-ID<mailman.515.1358190311.2939.python-list@python.org>
In reply to#36768
On Mon, Jan 14, 2013 at 11:51 AM, Ian Kelly <ian.g.kelly@gmail.com> wrote:
>> 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.

What's more, if the purpose of the syntax is to distinguish modules
from non-modules, then the syntax "os.path" (which you have stated
would not change) would be misleading, because the "path" part is in
fact a module.  Your proposed syntax fails to even achieve its stated
goal.

[toc] | [prev] | [next] | [standalone]


#36813

From"D'Arcy J.M. Cain" <darcy@druid.net>
Date2013-01-14 14:35 -0500
Message-ID<mailman.516.1358192162.2939.python-list@python.org>
In reply to#36768
On Mon, 14 Jan 2013 11:51:50 -0700
Ian Kelly <ian.g.kelly@gmail.com> wrote:
> On Sun, Jan 13, 2013 at 10:22 PM, Rick Johnson
> <rantingrickjohnson@gmail.com> wrote:
...Whatever

> If you want us to understand the syntax, then you need to define

If you are going to feed the trolls can I please ask that you Cc them
or send to them and Cc the list? That way those of us who filter out the
trolls can filter out the responses to them as well.

Thanks for understanding.

-- 
D'Arcy J.M. Cain <darcy@druid.net>         |  Democracy is three wolves
http://www.druid.net/darcy/                |  and a sheep voting on
+1 416 425 1212     (DoD#0082)    (eNTP)   |  what's for dinner.
IM: darcy@Vex.Net

[toc] | [prev] | [next] | [standalone]


Page 1 of 2  [1] 2  Next page →

Back to top | Article view | comp.lang.python


csiph-web