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


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

Re: Encapsulation in Python

Started byIan Kelly <ian.g.kelly@gmail.com>
First post2016-03-10 08:27 -0700
Last post2016-03-14 15:55 -0700
Articles 20 on this page of 49 — 10 participants

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

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  Re: Encapsulation in Python Ian Kelly <ian.g.kelly@gmail.com> - 2016-03-10 08:27 -0700
    Re: Encapsulation in Python Rick Johnson <rantingrickjohnson@gmail.com> - 2016-03-10 16:45 -0800
      Re: Encapsulation in Python Ian Kelly <ian.g.kelly@gmail.com> - 2016-03-11 08:47 -0700
        Re: Encapsulation in Python Rick Johnson <rantingrickjohnson@gmail.com> - 2016-03-11 18:39 -0800
          Re: Encapsulation in Python Ian Kelly <ian.g.kelly@gmail.com> - 2016-03-12 09:44 -0700
            Re: Encapsulation in Python Rick Johnson <rantingrickjohnson@gmail.com> - 2016-03-12 19:11 -0800
            Re: Encapsulation in Python Steven D'Aprano <steve@pearwood.info> - 2016-03-13 21:11 +1100
              Re: Encapsulation in Python Rick Johnson <rantingrickjohnson@gmail.com> - 2016-03-14 10:32 -0700
                Re: Encapsulation in Python Ian Kelly <ian.g.kelly@gmail.com> - 2016-03-14 15:09 -0600
                Re: Encapsulation in Python Mark Lawrence <breamoreboy@yahoo.co.uk> - 2016-03-14 21:23 +0000
                  Re: Encapsulation in Python BartC <bc@freeuk.com> - 2016-03-14 22:07 +0000
                    Re: Encapsulation in Python Mark Lawrence <breamoreboy@yahoo.co.uk> - 2016-03-14 22:20 +0000
                      Re: Encapsulation in Python BartC <bc@freeuk.com> - 2016-03-14 22:40 +0000
                        Re: Encapsulation in Python Mark Lawrence <breamoreboy@yahoo.co.uk> - 2016-03-14 23:19 +0000
                          Re: Encapsulation in Python BartC <bc@freeuk.com> - 2016-03-14 23:56 +0000
                            Re: Encapsulation in Python Chris Angelico <rosuav@gmail.com> - 2016-03-15 11:12 +1100
                              Re: Encapsulation in Python BartC <bc@freeuk.com> - 2016-03-15 00:54 +0000
                                Re: Encapsulation in Python Chris Angelico <rosuav@gmail.com> - 2016-03-15 11:58 +1100
                                  Re: Encapsulation in Python BartC <bc@freeuk.com> - 2016-03-15 01:22 +0000
                                    Re: Encapsulation in Python Chris Angelico <rosuav@gmail.com> - 2016-03-15 13:02 +1100
                            Re: Encapsulation in Python Mark Lawrence <breamoreboy@yahoo.co.uk> - 2016-03-15 00:28 +0000
                              Re: Encapsulation in Python BartC <bc@freeuk.com> - 2016-03-15 01:10 +0000
                                Re: Encapsulation in Python Chris Angelico <rosuav@gmail.com> - 2016-03-15 12:23 +1100
                                Re: Encapsulation in Python Mark Lawrence <breamoreboy@yahoo.co.uk> - 2016-03-15 04:41 +0000
                          Re: Encapsulation in Python rurpy@yahoo.com - 2016-03-14 17:17 -0700
                            Re: Encapsulation in Python Chris Angelico <rosuav@gmail.com> - 2016-03-15 11:25 +1100
                              Re: Encapsulation in Python Steven D'Aprano <steve@pearwood.info> - 2016-03-15 13:06 +1100
                                Re: Encapsulation in Python Chris Angelico <rosuav@gmail.com> - 2016-03-15 13:14 +1100
                                  Re: Encapsulation in Python Steven D'Aprano <steve@pearwood.info> - 2016-03-15 13:40 +1100
                                    Re: Encapsulation in Python Rick Johnson <rantingrickjohnson@gmail.com> - 2016-03-14 21:08 -0700
                            Re: Encapsulation in Python Mark Lawrence <breamoreboy@yahoo.co.uk> - 2016-03-15 00:47 +0000
                              Re: Encapsulation in Python Steven D'Aprano <steve@pearwood.info> - 2016-03-15 13:46 +1100
                            Re: Encapsulation in Python Chris Angelico <rosuav@gmail.com> - 2016-03-15 11:56 +1100
                            Re: Encapsulation in Python Mark Lawrence <breamoreboy@yahoo.co.uk> - 2016-03-15 04:36 +0000
                          Re: Encapsulation in Python Steven D'Aprano <steve@pearwood.info> - 2016-03-15 13:01 +1100
                            Re: Encapsulation in Python Mark Lawrence <breamoreboy@yahoo.co.uk> - 2016-03-15 04:45 +0000
                        Re: Encapsulation in Python Christian Gollwitzer <auriocus@gmx.de> - 2016-03-15 22:02 +0100
                          Re: Encapsulation in Python BartC <bc@freeuk.com> - 2016-03-16 00:39 +0000
                            Re: Encapsulation in Python BartC <bc@freeuk.com> - 2016-03-16 22:58 +0000
          Re: Encapsulation in Python sohcahtoa82@gmail.com - 2016-03-14 11:11 -0700
            Re: Encapsulation in Python Rick Johnson <rantingrickjohnson@gmail.com> - 2016-03-14 23:09 -0700
        Re: Encapsulation in Python Rick Johnson <rantingrickjohnson@gmail.com> - 2016-03-11 18:56 -0800
      Re: Encapsulation in Python Gregory Ewing <greg.ewing@canterbury.ac.nz> - 2016-03-12 13:52 +1300
        Re: Encapsulation in Python Rick Johnson <rantingrickjohnson@gmail.com> - 2016-03-12 08:49 -0800
          Re: Encapsulation in Python Chris Angelico <rosuav@gmail.com> - 2016-03-13 08:10 +1100
            Re: Encapsulation in Python Rick Johnson <rantingrickjohnson@gmail.com> - 2016-03-12 19:36 -0800
              Re: Encapsulation in Python Chris Angelico <rosuav@gmail.com> - 2016-03-13 15:05 +1100
          Re: Encapsulation in Python Gregory Ewing <greg.ewing@canterbury.ac.nz> - 2016-03-14 12:35 +1300
            Re: Encapsulation in Python Rick Johnson <rantingrickjohnson@gmail.com> - 2016-03-14 15:55 -0700

Page 1 of 3  [1] 2 3  Next page →


#104528 — Re: Encapsulation in Python

FromIan Kelly <ian.g.kelly@gmail.com>
Date2016-03-10 08:27 -0700
SubjectRe: Encapsulation in Python
Message-ID<mailman.139.1457623672.15725.python-list@python.org>
On Thu, Mar 10, 2016 at 6:41 AM, Ben Mezger <me@benmezger.nl> wrote:
> Hi all,
>
> I've been studying Object Oriented Theory using Java. Theoretically, all
> attributes should be private, meaning no one except the methods itself
> can access the attribute;
>
> public class Foo {
>     private int bar;
>     ...

Encapsulation in Python is based on trust rather than the
authoritarian style of C++ / Java. The maxim in the Python community
is that "we're all consenting adults". If I don't intend an attribute
to be messed with, then I'll mark it with a leading underscore. If you
mess with it anyway, and later your code breaks as a result of it,
that's your problem, not mine. :-)

> Normally in Java, we would write getters and setters to set/get the
> attribute bar. However, in Python, we normally create a class like so;
>
> class Foo(object):
>     bar = 0
>     ...
>
> And we usually don't write any getters/setters (though they exist in
> Python, I have not seen much projects making use of it).

The vast majority of getters and setters do nothing other than get/set
the field they belong to. They exist only to allow the *possibility*
of doing something else at some point far in the future. That's a ton
of undesirable boilerplate for little real benefit.

In Python, OO designers are able to get away with not using getters
and setters because we have properties. You can start with an
attribute, and if you later want to change the means of getting and
setting it, you just replace it with a property. The property lets you
add any logic you want, and as far as the outside world is concerned,
it still just looks like an attribute.

> We can easily encapsulate (data hiding) Foo's class using the '_'
> (underscore) when creating a new attribute, however, this would require
> all attributes to have a underscore.

A single leading underscore is just a naming convention, not true data
hiding, which isn't really possible in Python. Even the double
underscore only does name mangling, not true data hiding. It's meant
to prevent *accidental* naming collisions. You can still easily access
the attribute from outside the class if you're determined to.

This all boils down to the fact that code inside a method has no
special privilege over external code. If you could hide data so well
that external code really couldn't access it, then you wouldn't be
able to access it either.

[toc] | [next] | [standalone]


#104568

FromRick Johnson <rantingrickjohnson@gmail.com>
Date2016-03-10 16:45 -0800
Message-ID<6984dafc-fffd-4d46-a173-421bb5c142d2@googlegroups.com>
In reply to#104528
On Thursday, March 10, 2016 at 9:28:06 AM UTC-6, Ian wrote: 
> Encapsulation in Python is based on trust rather than the
> authoritarian style of C++ / Java. The maxim in the Python
> community is that "we're all consenting adults". If I
> don't intend an attribute to be messed with, then I'll
> mark it with a leading underscore. If you mess with it
> anyway, and later your code breaks as a result of it,
> that's your problem, not mine. :-)

It is a strange irony that you cannot escape the
encapsulating nature of Python modules (since they are
formed by Python from your source files), but Python freely
allows us to ignore encapsulation in our OOP paradigm...
Hmm, sure, many could argue that Python's "mandatory
modules" are simply a result of convenience, they will say:
"Since we have to write code in source files anyway, why not
utilize the "encapsulation of the source file itself to
define module scope?".

I have witnessed the mayhem that occurs when a language does
not mandate module encapsulation (Ruby, i'm looking directly
at you!!!!), and while i agree with the Python designers
that modules must *ALWAYS* be mandatory, i am not convinced
that module space should be so strictly confined to source
files.

Many times, i would have preferred to define my module space
across multiple files, multiple files that could share state
without resorting to the yoga-style "import contortions",
and/or the dreaded "circular import nightmares" that plague
our community today.

In one way, Python got it right by forcing us to encapsulate
our code into modules, however, it failed by not allowing us
to define both the breadth *AND* width of that encapsulation.
Which brings us up against the brutal reality that: Whilst
python's sycophants love to parrot-off about how we are all
"Adults", it's implementation still attempts to treat us
ignorant little children who are incapable of defining our
own module space.

> The vast majority of getters and setters do nothing other
> than get/set the field they belong to. They exist only to
> allow the *possibility* of doing something else at some
> point far in the future.

But you're ignoring the most important aspect of
getters/setters, and that is, that they expose an interface.
An interface that must be *EXPLICITLY* created. Good
interfaces *NEVER* happen by accident.

> That's a ton of undesirable boilerplate for little real
> benefit.

I understand the aversion to boilerplate, but most languages
have simplified the creation of getters/setters to the point
that your lament is unfounded. And i would argue that the
benefits of creating rigid interfaces is the gift that
keeps on giving.

> In Python, OO designers are able to get away with not
> using getters and setters because we have properties. You
> can start with an attribute, and if you later want to
> change the means of getting and setting it, you just
> replace it with a property. The property lets you add any
> logic you want, and as far as the outside world is
> concerned, it still just looks like an attribute.

I used properties quite often when i first began writing
Python code. Heck, i thought they were the best thing since
sliced bread. But now, i have come to hate them. I never use
them in any new code, and when i have free time, i strip
them out of old code. When i am forced to use an interface
that was written with properties, i find that learning the
interface is more difficult

  (1) In a dir listing, one cannot determine which symbols
  are properties, which are attributes, and which are
  methods. The beauty of pure OOP encapsulation, is that,
  *EVERY* exposed symbol is a method. In pure OOP, i don't
  have to wonder if i'm calling a function with no
  parameters, or accessing a property, or accessing an
  attribute, no, i'll know that every access is through a
  method, therefore, i will append "()" when i know the
  method takes no arguments. Consistency is very important.
      
  (2) Properties and attributes encourage vague naming
  schemes. When i read code, i find the code more
  comprehensible when the symbols give me clues as to what
  is going on. So if i read code like: `re.groups`,
  befuddlement sets in. What is "groups"? A function
  object? An attribute? "getCapturingGroupCount" would be a
  better name (but that's semantics) In pure OOP,  methods
  are the only communication meduim, so we're more likely to
  write "getBlah" and "setBlah", and use verbs for
  procedural names -- these naming conventions are more
  comprehensible to the user.
    
  (3) Not all authors correctly utilize leading underscores
  to differentiate between public and private attributes.
  
> This all boils down to the fact that code inside a method
> has no special privilege over external code. If you could
> hide data so well that external code really couldn't
> access it, then you wouldn't be able to access it either.

That's a ridiculous statement Ian.

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


#104622

FromIan Kelly <ian.g.kelly@gmail.com>
Date2016-03-11 08:47 -0700
Message-ID<mailman.25.1457711277.26429.python-list@python.org>
In reply to#104568
On Thu, Mar 10, 2016 at 5:45 PM, Rick Johnson
<rantingrickjohnson@gmail.com> wrote:
> Many times, i would have preferred to define my module space
> across multiple files, multiple files that could share state
> without resorting to the yoga-style "import contortions",
> and/or the dreaded "circular import nightmares" that plague
> our community today.

Sounds to me like you're blaming Python for your own poor design.
Possible solutions:

1) Don't do that. If your module is too big for one file, then it's
likely poorly organized and doesn't all belong in one module anyway.

2) Clearly define which module is to be imported first. Then follow
it. When module b is imported, it should import module a. When module
a is imported, it *shouldn't* import module b until it's defined all
of its own members first. If module a depends on anything from module
b at import time, then refactor so it doesn't. This doesn't require
"contortions".

3) Just put all your damn shared state in a class. There's nothing
stopping you from spreading out your class method definitions over
multiple files if you really want to, and it solves your import issue
by allowing everything to be imported before you even begin to set up
the shared state.

>> The vast majority of getters and setters do nothing other
>> than get/set the field they belong to. They exist only to
>> allow the *possibility* of doing something else at some
>> point far in the future.
>
> But you're ignoring the most important aspect of
> getters/setters, and that is, that they expose an interface.
> An interface that must be *EXPLICITLY* created. Good
> interfaces *NEVER* happen by accident.

And you're suggesting that public attributes and properties do not
expose an interface? Rubbish.

>> That's a ton of undesirable boilerplate for little real
>> benefit.
>
> I understand the aversion to boilerplate, but most languages
> have simplified the creation of getters/setters to the point
> that your lament is unfounded. And i would argue that the
> benefits of creating rigid interfaces is the gift that
> keeps on giving.

I don't care how easy they are to *create*. Code is read much more
often than it is written, and excessive boilerplate damages
readability.

>> In Python, OO designers are able to get away with not
>> using getters and setters because we have properties. You
>> can start with an attribute, and if you later want to
>> change the means of getting and setting it, you just
>> replace it with a property. The property lets you add any
>> logic you want, and as far as the outside world is
>> concerned, it still just looks like an attribute.
>
> I used properties quite often when i first began writing
> Python code. Heck, i thought they were the best thing since
> sliced bread. But now, i have come to hate them. I never use
> them in any new code, and when i have free time, i strip
> them out of old code. When i am forced to use an interface
> that was written with properties, i find that learning the
> interface is more difficult
>
>   (1) In a dir listing, one cannot determine which symbols
>   are properties, which are attributes, and which are
>   methods. The beauty of pure OOP encapsulation, is that,
>   *EVERY* exposed symbol is a method. In pure OOP, i don't
>   have to wonder if i'm calling a function with no
>   parameters, or accessing a property, or accessing an
>   attribute, no, i'll know that every access is through a
>   method, therefore, i will append "()" when i know the
>   method takes no arguments. Consistency is very important.

How do you know the method takes no arguments from a dir listing? If
you think the method does take arguments, how do you find out what
those are from a dir listing? If you want to do actual coding with a
class, you're eventually going to have to read something other than
the dir listing, whether everything is a method or not.

>   (2) Properties and attributes encourage vague naming
>   schemes. When i read code, i find the code more
>   comprehensible when the symbols give me clues as to what
>   is going on. So if i read code like: `re.groups`,
>   befuddlement sets in. What is "groups"? A function
>   object? An attribute? "getCapturingGroupCount" would be a
>   better name (but that's semantics)

Actually, it would be wrong. Match.groups doesn't return a count.
Also, it's a method, not an attribute or property, so as an example it
sort of destroys your argument that using methods naturally results in
giving the methods good, meaningful names. These are merely separate
aspects of interface design.

>   In pure OOP,  methods
>   are the only communication meduim, so we're more likely to
>   write "getBlah" and "setBlah", and use verbs for
>   procedural names -- these naming conventions are more
>   comprehensible to the user.

Good names for methods are *descriptive* verb phrases. Good names for
attributes and properties are *descriptive* nouns or noun phrases. Do
you really believe that verbs are somehow inherently easier to
understand?

>   (3) Not all authors correctly utilize leading underscores
>   to differentiate between public and private attributes.
>
>> This all boils down to the fact that code inside a method
>> has no special privilege over external code. If you could
>> hide data so well that external code really couldn't
>> access it, then you wouldn't be able to access it either.
>
> That's a ridiculous statement Ian.

I invite you to demonstrate a counter-example. Show me where a Python
method can hide data such that code external to the class can't find
it.

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


#104667

FromRick Johnson <rantingrickjohnson@gmail.com>
Date2016-03-11 18:39 -0800
Message-ID<4ddc3696-3f71-4598-98a6-929267f51fb9@googlegroups.com>
In reply to#104622
On Friday, March 11, 2016 at 9:48:22 AM UTC-6, Ian wrote:
> On Thu, Mar 10, 2016 at 5:45 PM, Rick Johnson
> The honorable Rick Johnson wrote:
> > Many times, i would have preferred to define my module space
> > across multiple files, multiple files that could share state
> > without resorting to the yoga-style "import contortions",
> > and/or the dreaded "circular import nightmares" that plague
> > our community today.
>
> Sounds to me like you're blaming Python for your own poor design.
> Possible solutions:
>
> 1) Don't do that. If your module is too big for one file, then it's
> likely poorly organized and doesn't all belong in one module anyway.

Apparently you've missed the many heated arguments between
Chris Angelico and myself concerning the size of source
files. I have *ALWAYS* taken the position that source files
should be kept as small as possible, but that position is
more relevant in Python, were modules are defined by a
single source file. I don't take the Java position that a
module can only contain one class, but i like to keep the
number of classes (IN MY SOURCE FILES) small.

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. The size of a "run-time module"
is irrelevant in most languages, but here in Python, were
module namespace is defined by the contents of *ONE SINGLE
SOURCE FILE*, the whole ballgame is changed. If i need to
create a module that contains many exposed symbols in
Python, i'm forced to do one of the following:

  (1) Write all my code in a single *GIGANTIC* file...

or

  (2) Create one file that will be the "mother-ship module",
  and N files that will be the "satellite modules", and from
  inside the mother-ship, import all the symbols from all
  the satellites. Ha, but in reality, it's not that simple,
  because state does not "magically" travel between modules!

    ##########
    # foo.py #
    ##########
    FOO_SHARED_STATE = "foo"
    import _fooSatilite1
    _fooSatilite1.FOO_SHARED_STATE = FOO_SHARED_STATE
    from _fooSatilite1 import *
    import _fooSatilite2
    _fooSatilite2.FOO_SHARED_STATE = FOO_SHARED_STATE
    from _fooSatilite2 import *
    print 'This is the mother-ship called foo'
    ...

    ####################
    # _fooSatilite1.py #
    ####################
    from _fooConstants import *
    print 'This is foo-fighter1, reporting for duty'
    print FOO_SHARED_STATE
    ...

    ####################
    # _fooSatilite2.py #
    ####################
    from _fooConstants import *
    print 'This is foo-fighter2, reporting for duty'
    print FOO_SHARED_STATE
    ...

But i find both to be absurd. Writing all code in a single
file might be fine for a toy module that contains a handful
of functions or classes or vars, but once we start creating 
anything in the "professional size range", it will become 
an "editing nightmare" of epic proportions!

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!

 (3) Allow a programmer to define module space at will

    ##########
    # foo.py #
    ##########
    module foo
    FOO_SHARED_STATE = "foo"
    print 'This is the mother-ship called foo'
    ...

    ####################
    # _fooSatilite1.py #
    ####################
    module foo
    print 'This is foo-fighter1, reporting for duty'
    print FOO_SHARED_STATE # NO MP REQUIRED!
    ...

    ####################
    # _fooSatilite2.py #
    ####################
    module foo
    print 'This is foo-fighter2, reporting for duty'
    print FOO_SHARED_STATE # NO MP REQUIRED!
    ...

No need for import contortions, no need for monkey patching,
but most importantly, no need for professional programmers
to feel as though they are penchant little children, who
need their "module diapers" wrapped for them by mommy
Python, who, after popping one too many "mother's little
helpers", has a nasty habit of wrapping our diapers too damn
tight -- what a drag, it is, getting old...

> 2) Clearly define which module is to be imported first. Then follow
> it. When module b is imported, it should import module a. When module
> a is imported, it *shouldn't* import module b until it's defined all
> of its own members first. If module a depends on anything from module
> b at import time, then refactor so it doesn't. This doesn't require
> "contortions".

That sounds simple in theory, but it breaks down quickly
when you create "professional sized programs"

> 3) Just put all your damn shared state in a class. There's nothing
> stopping you from spreading out your class method definitions over
> multiple files if you really want to, and it solves your import issue
> by allowing everything to be imported before you even begin to set up
> the shared state.

Your words tell me that you have not written anything substantial.

> And you're suggesting that public attributes and properties do not
> expose an interface? Rubbish.

No, what i'm suggesting, is that, from the POV of a dir
listing, they *ALL* look the same.

> I don't care how easy they are to *create*. Code is read much more
> often than it is written, and excessive boilerplate damages
> readability.

I understand the importance of readability, but is usability
of no concern to you? In fact, i would argue that, when
*ROCK SOLID* professional interfaces are combined with
proper documentation and strict adherence to style guides,
there is no need to read source code.

The only person who should be reading source, is a
maintenance programmer. And if the code was designed
properly, his job would be mostly just adding a feature here
or there, or repairing a small bug here or there -- any code
monkey can do that!

> >   (2) Properties and attributes encourage vague naming
> >   schemes. When i read code, i find the code more
> >   comprehensible when the symbols give me clues as to what
> >   is going on. So if i read code like: `re.groups`,
> >   befuddlement sets in. What is "groups"? A function
> >   object? An attribute? "getCapturingGroupCount" would be a
> >   better name (but that's semantics)
>
> Actually, it would be wrong. Match.groups doesn't return a count.

Who said anything about match objects?

############################################################
# BEGIN INTERACTIVE SESSION
############################################################
py> import re
py> prog = re.compile(r'(Ian) (\w+)')
py> prog?
['findall', 'finditer', 'flags', 'groupindex', 'groups', 'match', 'pattern', 'scanner', 'search', 'split', 'sub', 'subn']
py> prog.groups
2
py> prog.groups?type
<type 'int'>
############################################################
# END INTERACTIVE SESSION
############################################################

Looks like an integer to me. (Well, i'll admit, first you'll
have to parse my mini-language syntax, but it's highly
intuitive -- more than a Python dir listing, i'll tell you
that much!)

> >   In pure OOP,  methods
> >   are the only communication meduim, so we're more likely to
> >   write "getBlah" and "setBlah", and use verbs for
> >   procedural names -- these naming conventions are more
> >   comprehensible to the user.
>
> Good names for methods are *descriptive* verb phrases. Good names for
> attributes and properties are *descriptive* nouns or noun phrases. Do
> you really believe that verbs are somehow inherently easier to
> understand?

When i see "get_width" or "set_width", i know that the first is
returning the width, and the second will set the width. And
anyone with an IQ over room temperature, can surmise that
set_width takes at least one argument.

However, when i see "width", how the hell am i supposed to
know if it is a read-only attribute, a property, or a method?
Must i read source code just to find this out? Sure, if the
author included a useful doc string, i could pull it up, but
to me, this is a giant waste of time. Self documenting names
are the *KEY* to short learning curves.

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


#104714

FromIan Kelly <ian.g.kelly@gmail.com>
Date2016-03-12 09:44 -0700
Message-ID<mailman.42.1457801128.12893.python-list@python.org>
In reply to#104667
On Fri, Mar 11, 2016 at 7:39 PM, Rick Johnson
<rantingrickjohnson@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.

>   (2) Create one file that will be the "mother-ship module",
>   and N files that will be the "satellite modules", and from
>   inside the mother-ship, import all the symbols from all
>   the satellites. Ha, but in reality, it's not that simple,
>   because state does not "magically" travel between modules!
>
>     ##########
>     # foo.py #
>     ##########
>     FOO_SHARED_STATE = "foo"
>     import _fooSatilite1
>     _fooSatilite1.FOO_SHARED_STATE = FOO_SHARED_STATE
>     from _fooSatilite1 import *
>     import _fooSatilite2
>     _fooSatilite2.FOO_SHARED_STATE = FOO_SHARED_STATE
>     from _fooSatilite2 import *
>     print 'This is the mother-ship called foo'
>     ...
>
>     ####################
>     # _fooSatilite1.py #
>     ####################
>     from _fooConstants import *
>     print 'This is foo-fighter1, reporting for duty'
>     print FOO_SHARED_STATE
>     ...
>
>     ####################
>     # _fooSatilite2.py #
>     ####################
>     from _fooConstants import *
>     print 'This is foo-fighter2, reporting for duty'
>     print FOO_SHARED_STATE
>     ...
>
> But i find both to be absurd. Writing all code in a single
> file might be fine for a toy module that contains a handful
> of functions or classes or vars, but once we start creating
> anything in the "professional size range", it will become
> an "editing nightmare" of epic proportions!
>
> 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!
>
>  (3) Allow a programmer to define module space at will
>
>     ##########
>     # foo.py #
>     ##########
>     module foo
>     FOO_SHARED_STATE = "foo"
>     print 'This is the mother-ship called foo'
>     ...
>
>     ####################
>     # _fooSatilite1.py #
>     ####################
>     module foo
>     print 'This is foo-fighter1, reporting for duty'
>     print FOO_SHARED_STATE # NO MP REQUIRED!
>     ...
>
>     ####################
>     # _fooSatilite2.py #
>     ####################
>     module foo
>     print 'This is foo-fighter2, reporting for duty'
>     print FOO_SHARED_STATE # NO MP REQUIRED!
>     ...

Is this meant to be equivalent to the other example? In that example,
you have the two "satellite" modules being imported between the
definition of FOO_SHARED_STATE and the print. In this example, how on
Earth is Python supposed to know that after the FOO_SHARED_STATE line
it's supposed to switch to executing these other two files before
continuing on to the next statement?

More generally, what order do you expect these files to be executed in
when the "module" is imported? There must be some defined order,
because Python isn't magically capable of executing all three of them
simultaneously. If there's a defined order, then you should be able to
easily add explicit import statements at the tops of modules that
declare that order. So this is exactly the same as your "import
contortions" except that you want to make the reader (and the Python
interpreter) have to guess at the dependencies instead of making them
explicit.

> No need for import contortions, no need for monkey patching,
> but most importantly, no need for professional programmers
> to feel as though they are penchant little children, who
> need their "module diapers" wrapped for them by mommy
> Python, who, after popping one too many "mother's little
> helpers", has a nasty habit of wrapping our diapers too damn
> tight -- what a drag, it is, getting old...
>
>> 2) Clearly define which module is to be imported first. Then follow
>> it. When module b is imported, it should import module a. When module
>> a is imported, it *shouldn't* import module b until it's defined all
>> of its own members first. If module a depends on anything from module
>> b at import time, then refactor so it doesn't. This doesn't require
>> "contortions".
>
> That sounds simple in theory, but it breaks down quickly
> when you create "professional sized programs"

I find in interesting that you seem to be equating "very large" with
"professional". In my view, it's exactly the opposite. Anything very
large and so unorganized looks rather sloppy and unprofessional.


>> 3) Just put all your damn shared state in a class. There's nothing
>> stopping you from spreading out your class method definitions over
>> multiple files if you really want to, and it solves your import issue
>> by allowing everything to be imported before you even begin to set up
>> the shared state.
>
> Your words tell me that you have not written anything substantial.

I'll take your lack of substantive reply to mean "Huh, I never thought
of this approach that both solves my problem and improves the
structure of my code at the same time. Better hurl an insult to save
face!" Compliment accepted.

> I understand the importance of readability, but is usability
> of no concern to you? In fact, i would argue that, when
> *ROCK SOLID* professional interfaces are combined with
> proper documentation and strict adherence to style guides,
> there is no need to read source code.
>
> The only person who should be reading source, is a
> maintenance programmer. And if the code was designed
> properly, his job would be mostly just adding a feature here
> or there, or repairing a small bug here or there -- any code
> monkey can do that!

Yeah, you're so right. Professional software is write-once,
run-forever. Software requirements never change, and original designs
never have unforeseen consequences. "Maintenance" programmers exist as
some lower breed of programmer who are barely unable to understand how
loops work, much less invent thousands of distinct symbols to cram
into a single module so that they too can be considered professional
programmers.

</sarcasm>

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


#104743

FromRick Johnson <rantingrickjohnson@gmail.com>
Date2016-03-12 19:11 -0800
Message-ID<b2c7971d-40ab-4636-bb3e-d7711888663a@googlegroups.com>
In reply to#104714
On Saturday, March 12, 2016 at 10:45:43 AM UTC-6, Ian wrote:
> On Fri, Mar 11, 2016 at 7:39 PM, Rick Johnson
> <rantingrickjohnson@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? 

I use words, mostly.

> > [SNIP: Two Examples From Rick]
>
> Is this meant to be equivalent to the other example? In that example,
> you have the two "satellite" modules being imported between the
> definition of FOO_SHARED_STATE and the print. In this example, how on
> Earth is Python supposed to know that after the FOO_SHARED_STATE line
> it's supposed to switch to executing these other two files before
> continuing on to the next statement?

The examples i provided are too simplistic to convey such
details, because they were never meant to convey such
details. Of *COURSE* you'll encounter issues in *real code*
if you don't organize it's execution correctly. Spreading
the contents of a module across multiple source files does
not prevent NameErrors from raising, and it shouldn't. Heck,
you can easily break a python module today, by referencing
a symbol too early:

    ##############
    # example.py #
    ##############
    bar = Bar()   
     
    class Bar(object):
        pass

> > That sounds simple in theory, but it breaks down quickly
> > when you create "professional sized programs"
> 
> I find in interesting that you seem to be equating "very large" with
> "professional". In my view, it's exactly the opposite. Anything very
> large and so unorganized looks rather sloppy and unprofessional.

I find it interesting that you seem to be equating "very
large" with "sloppy". Not all large software's are sloppy,
and not all small software's are neat. Dealing in absolutes
is never a good idea.

> >> 3) Just put all your damn shared state in a class. There's nothing
> >> stopping you from spreading out your class method definitions over
> >> multiple files if you really want to, and it solves your import issue
> >> by allowing everything to be imported before you even begin to set up
> >> the shared state.
> >
> > Your words tell me that you have not written anything substantial.
> 
> I'll take your lack of substantive reply to mean "Huh, I never thought
> of this approach that both solves my problem and improves the
> structure of my code at the same time. Better hurl an insult to save
> face!" Compliment accepted.

Why must I invoke the awesome "instancing power" of a
SharedStateObject, when a singleton would be a more
appropriate design? But even a singleton would be a nasty
hack for: sharing state across a "module space" that is 
defined in multiple source files.

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


#104753

FromSteven D'Aprano <steve@pearwood.info>
Date2016-03-13 21:11 +1100
Message-ID<56e53cd3$0$1586$c3e8da3$5496439d@news.astraweb.com>
In reply to#104714
On Sun, 13 Mar 2016 03:44 am, Ian Kelly wrote:

> On Fri, Mar 11, 2016 at 7:39 PM, Rick Johnson
> <rantingrickjohnson@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:

py> len(dir(os))
224


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:

py> len(dir(decimal))
79


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



-- 
Steven

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


#104847

FromRick Johnson <rantingrickjohnson@gmail.com>
Date2016-03-14 10:32 -0700
Message-ID<1376c684-2e7f-417a-9683-e47789f019fe@googlegroups.com>
In reply to#104753
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@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.

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


#104862

FromIan Kelly <ian.g.kelly@gmail.com>
Date2016-03-14 15:09 -0600
Message-ID<mailman.130.1457989824.12893.python-list@python.org>
In reply to#104847
On Mon, Mar 14, 2016 at 11:32 AM, Rick Johnson
<rantingrickjohnson@gmail.com> wrote:
> 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?

In that particular case, I wouldn't, except possibly as an
implementation detail with the main OpenGL package importing the
contents of all its sub-packages into itself (and I think that if you
look at the PyOpenGL source you'll find that it's doing something
similar). It's following a well-documented API that is separate from
its Python wrapper. It's unfortunate that the only namespacing
considered in the design of that API was "everything starts with the
prefix gl", but that's what we're stuck with. Moving things around
would just confuse users who can't then find them where they expect.

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


#104865

FromMark Lawrence <breamoreboy@yahoo.co.uk>
Date2016-03-14 21:23 +0000
Message-ID<mailman.132.1457990663.12893.python-list@python.org>
In reply to#104847
On 14/03/2016 21:09, Ian Kelly wrote:
> On Mon, Mar 14, 2016 at 11:32 AM, Rick Johnson
> <rantingrickjohnson@gmail.com> wrote:
>> 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?
>
> In that particular case, I wouldn't, except possibly as an
> implementation detail with the main OpenGL package importing the
> contents of all its sub-packages into itself (and I think that if you
> look at the PyOpenGL source you'll find that it's doing something
> similar). It's following a well-documented API that is separate from
> its Python wrapper. It's unfortunate that the only namespacing
> considered in the design of that API was "everything starts with the
> prefix gl", but that's what we're stuck with. Moving things around
> would just confuse users who can't then find them where they expect.
>

If it was reorganised rr would claim that it had split the community in 
the same way that the disastrous migration from Python 2 to 3 has done. 
  The minor snag to his argument is that I'm not aware of any such split.

Python 2.8, RickedPython, and the latest entry into the race, 
BartCPython, all vapourware.  At least rr knows something about 
tkinter/IDLE, whereas the latter appears to know squat about anything. 
You can fool all of the programmers, all of the time?

-- 
My fellow Pythonistas, ask not what our language can do for you, ask
what you can do for our language.

Mark Lawrence

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


#104866

FromBartC <bc@freeuk.com>
Date2016-03-14 22:07 +0000
Message-ID<nc7chi$lbu$1@dont-email.me>
In reply to#104865
On 14/03/2016 21:23, Mark Lawrence wrote:

> Python 2.8, RickedPython, and the latest entry into the race,
> BartCPython, all vapourware.

I'm not creating a new version of Python or CPython (you should have 
used an underscore).

But I do have considerable experience of creating dynamically-typed 
languages and writing byte-code interpreters for them. They are not 
vapourware.

-- 
Bartc

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


#104868

FromMark Lawrence <breamoreboy@yahoo.co.uk>
Date2016-03-14 22:20 +0000
Message-ID<mailman.133.1457994074.12893.python-list@python.org>
In reply to#104866
On 14/03/2016 22:07, BartC wrote:
> On 14/03/2016 21:23, Mark Lawrence wrote:
>
>> Python 2.8, RickedPython, and the latest entry into the race,
>> BartCPython, all vapourware.
>
> I'm not creating a new version of Python or CPython (you should have
> used an underscore).
>
> But I do have considerable experience of creating dynamically-typed
> languages and writing byte-code interpreters for them. They are not
> vapourware.
>

Really?  So why do you keep arguing, most notably with Steven D'Aprano, 
about the benefits of dynamic typing, whereby you appear to be 
completely against it?

The RUE kept stating that he was an expert in unicode, but never once 
provided a single shred of evidence to support his claim.  Until I see 
substantiated evidence from you I am going to state quite cleary that 
you've no idea, you're just another RUE.  Your dreadful piece of code 
published earlier today around a switch statement summed it up.  When 
are you running the profile that I asked for?

-- 
My fellow Pythonistas, ask not what our language can do for you, ask
what you can do for our language.

Mark Lawrence

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


#104871

FromBartC <bc@freeuk.com>
Date2016-03-14 22:40 +0000
Message-ID<nc7ef9$sgf$1@dont-email.me>
In reply to#104868
On 14/03/2016 22:20, Mark Lawrence wrote:
> On 14/03/2016 22:07, BartC wrote:
>> On 14/03/2016 21:23, Mark Lawrence wrote:
>>
>>> Python 2.8, RickedPython, and the latest entry into the race,
>>> BartCPython, all vapourware.
>>
>> I'm not creating a new version of Python or CPython (you should have
>> used an underscore).
>>
>> But I do have considerable experience of creating dynamically-typed
>> languages and writing byte-code interpreters for them. They are not
>> vapourware.
>>
>
> Really?  So why do you keep arguing, most notably with Steven D'Aprano,
> about the benefits of dynamic typing, whereby you appear to be
> completely against it?

I'm not against dynamic typing.

I'm against mutable, dynamic names, among other dynamic features that 
are well known to make Python hard to optimise, and which for me appear 
to give little added value.

  Your dreadful piece of code
> published earlier today around a switch statement summed it up.

Was that in Python? It was /supposed/ to be dreadful. I was making a 
case for it to be supported directly.

 > The RUE kept stating that he was an expert in unicode, but never once
 > provided a single shred of evidence to support his claim.  Until I see
 > substantiated evidence from you I am going to state quite cleary that
 > you've no idea, you're just another RUE.

Sorry, I'm not going to do that, and I don't expect anyone here to have 
to do so either. You will have to take my posts as they are.

-- 
Bartc

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


#104875

FromMark Lawrence <breamoreboy@yahoo.co.uk>
Date2016-03-14 23:19 +0000
Message-ID<mailman.137.1457997645.12893.python-list@python.org>
In reply to#104871
On 14/03/2016 22:40, BartC wrote:
> On 14/03/2016 22:20, Mark Lawrence wrote:
>> On 14/03/2016 22:07, BartC wrote:
>>> On 14/03/2016 21:23, Mark Lawrence wrote:
>>>
>>>> Python 2.8, RickedPython, and the latest entry into the race,
>>>> BartCPython, all vapourware.
>>>
>>> I'm not creating a new version of Python or CPython (you should have
>>> used an underscore).
>>>
>>> But I do have considerable experience of creating dynamically-typed
>>> languages and writing byte-code interpreters for them. They are not
>>> vapourware.
>>>
>>
>> Really?  So why do you keep arguing, most notably with Steven D'Aprano,
>> about the benefits of dynamic typing, whereby you appear to be
>> completely against it?
>
> I'm not against dynamic typing.
>
> I'm against mutable, dynamic names, among other dynamic features that
> are well known to make Python hard to optimise, and which for me appear
> to give little added value.

There is no need to optimise python, it is fast enough.  For me every 
advantage of Python is that I can do what I like with it, when I like 
with it, and I'm not stuck in the dreadful straight jacket of the 
statically typed languages.  If someone wants to make it faster I'm not 
going to complain, but your obsession with speed is going to have me 
dying of laughter if this goes on much longer.

>
>   Your dreadful piece of code
>> published earlier today around a switch statement summed it up.
>
> Was that in Python? It was /supposed/ to be dreadful. I was making a
> case for it to be supported directly.

You mean the huge great long list of hard coded function calls.  They 
are directly supported.  So is the loop.  Anything wrong with the Paul 
Rubin response?  And as my earlier link showed you often simply don't 
need a switch statement in an OO language.  Not much point providing 
something, much worse optimising it, if it isn't needed in the first place?

>
>  > The RUE kept stating that he was an expert in unicode, but never once
>  > provided a single shred of evidence to support his claim.  Until I see
>  > substantiated evidence from you I am going to state quite cleary that
>  > you've no idea, you're just another RUE.
>
> Sorry, I'm not going to do that, and I don't expect anyone here to have
> to do so either. You will have to take my posts as they are.
>

Drivel.  Any establised member of this community, or any other community 
for that matter, will always publish, unless, like the RUE, they've got 
something to hide.  So you're just a chicken.  Where do you buy the 
paint from for the streaks down your back?  Just in case you can't guess 
it is yellow.  I'll state the colour just in case your knowledge of 
colours is the same as your so called knowledge of computing, something 
of which I'm far from persuaded, on the grounds that speed simply is not 
the sole criteria for a language.

-- 
My fellow Pythonistas, ask not what our language can do for you, ask
what you can do for our language.

Mark Lawrence

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


#104877

FromBartC <bc@freeuk.com>
Date2016-03-14 23:56 +0000
Message-ID<nc7it9$ejq$1@dont-email.me>
In reply to#104875
On 14/03/2016 23:19, Mark Lawrence wrote:
> On 14/03/2016 22:40, BartC wrote:

>> Was that in Python? It was /supposed/ to be dreadful. I was making a
>> case for it to be supported directly.
>
> You mean the huge great long list of hard coded function calls.  They
> are directly supported.  So is the loop.  Anything wrong with the Paul
> Rubin response?

I tried it. It wasn't bad, but still 1/3 the speed of an if-elif chain 
with discrete range-checking.

> And as my earlier link showed you often simply don't
> need a switch statement in an OO language.  Not much point providing
> something, much worse optimising it, if it isn't needed in the first place?

I disagree. And presumably so do others as there are so many different 
attempts to implement switch, with varying degrees of success. Here's 
how I do it outside Python:

  switch c
  when 'A'..'Z','a'..'z','_' then
      ++name
  when '0'..'9' then
      ++numeric
  when "()[]<>{}" then
      ++brackets
  else
      ++other
  end

Anything so terrible about that that Python needs to keep well clear of 
or that you think its users should be deprived of?

>> Sorry, I'm not going to do that, and I don't expect anyone here to have
>> to do so either. You will have to take my posts as they are.
>>
>
> Drivel.  Any establised member of this community, or any other community
> for that matter, will always publish, unless, like the RUE, they've got
> something to hide.  So you're just a chicken.  Where do you buy the
> paint from for the streaks down your back?

OK, we've got another Rod Speed! He also gets a kick out of being rude 
and insulting to everyone.

> on the grounds that speed simply is not
> the sole criteria for a language.

I agree with you. But once you've got the language right, then there's 
no harm looking at performance. A switch statement like the above can be 
executed in a single byte-code.

-- 
Bartc

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


#104879

FromChris Angelico <rosuav@gmail.com>
Date2016-03-15 11:12 +1100
Message-ID<mailman.138.1458000749.12893.python-list@python.org>
In reply to#104877
On Tue, Mar 15, 2016 at 10:56 AM, BartC <bc@freeuk.com> wrote:
> I disagree. And presumably so do others as there are so many different
> attempts to implement switch, with varying degrees of success. Here's how I
> do it outside Python:
>
>  switch c
>  when 'A'..'Z','a'..'z','_' then
>      ++name
>  when '0'..'9' then
>      ++numeric
>  when "()[]<>{}" then
>      ++brackets
>  else
>      ++other
>  end
>
> Anything so terrible about that that Python needs to keep well clear of or
> that you think its users should be deprived of?

Yes: the complete lack of colons at the ends of lines that introduce
suites. This is utterly unacceptable in Python!

Seriously though - the one thing that I'm very concerned about here is
your brackets one. In Python, there's no reason to restrict 'switch'
to integers, so I would expect its semantics to be based on either
equality comparisons or inequality comparisons (possibly with a
requirement that all values be hashable); you could have something
like "when in <string>" but a simple "when <string>" would look to me
like it's testing for that entire string. (Don't forget that, in
Python, there's no difference between 'single quoted strings' and
"double quoted strings", as there is in C-like languages.)

Although... come to think of it, you could actually define it the
other way around: the 'when' statement checks if the current switch
object is contained within any of its arguments. Coupled with a
range-like object with its own literal syntax, that would pretty much
give you what you're looking at there. However, you'd need to have an
awkward notation for the cases where you _are_ looking for equality:

switch c:
    when 'A'..'Z', 'a'..'z', ['_']:
        ++name

Or, in a long tree:

switch c:
    when [1]:
        ...
    when [2]:
        ...
    when [3]:
        ...

Which could work. It'd be well-defined, and not unreasonable. It
would, however, be entirely predicated on a "comparison range" object
with a literal syntax:

class Range:
    def __init__(self, start, stop):
        self.start = start
        self.stop = stop
    def __contains__(self, obj):
        return self.start <= obj <= self.stop
    def __repr__(self):
        return "%r..%r" % (self.start, self.stop)

But that's not overly hard either.

ChrisA

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


#104889

FromBartC <bc@freeuk.com>
Date2016-03-15 00:54 +0000
Message-ID<nc7man$obt$1@dont-email.me>
In reply to#104879
On 15/03/2016 00:12, Chris Angelico wrote:
> On Tue, Mar 15, 2016 at 10:56 AM, BartC <bc@freeuk.com> wrote:

>>   switch c
>>   when 'A'..'Z','a'..'z','_' then
>>       ++name

>> Anything so terrible about that that Python needs to keep well clear of or
>> that you think its users should be deprived of?
>
> Yes: the complete lack of colons at the ends of lines that introduce
> suites. This is utterly unacceptable in Python!
>
> Seriously though - the one thing that I'm very concerned about here is
> your brackets one.

Yeah, I'm not sure about that either. I'd already written:

  when '(', ')', ....

when I thought having a string constant here would be neat, and 
implemented that just before posting.

> In Python, there's no reason to restrict 'switch'
> to integers, so I would expect its semantics to be based on either
> equality comparisons or inequality comparisons

I use two forms of switch: one for integers only (very fast), and the 
other for any other values, which does tests in sequence.

> (possibly with a
> requirement that all values be hashable); you could have something
> like "when in <string>" but a simple "when <string>" would look to me
> like it's testing for that entire string. (Don't forget that, in
> Python, there's no difference between 'single quoted strings' and
> "double quoted strings", as there is in C-like languages.)
>
> Although... come to think of it, you could actually define it the
> other way around: the 'when' statement checks if the current switch
> object is contained within any of its arguments. Coupled with a
> range-like object with its own literal syntax, that would pretty much
> give you what you're looking at there. However, you'd need to have an
> awkward notation for the cases where you _are_ looking for equality:
>
> switch c:
>      when 'A'..'Z', 'a'..'z', ['_']:
>          ++name
>
> Or, in a long tree:
>
> switch c:
>      when [1]:
>          ...
>      when [2]:
>          ...
>      when [3]:
>          ...
>
> Which could work. It'd be well-defined, and not unreasonable. It
> would, however, be entirely predicated on a "comparison range" object
> with a literal syntax:
>
> class Range:
>      def __init__(self, start, stop):
>          self.start = start
>          self.stop = stop
>      def __contains__(self, obj):
>          return self.start <= obj <= self.stop
>      def __repr__(self):
>          return "%r..%r" % (self.start, self.stop)
>
> But that's not overly hard either.

The tests I do for the more general switch are either equality, or 'in' 
for certain combinations of types (mainly testing integers for 
membership of ranges and sets. Sets are Pascal-style bit-sets).

I've also looked at the problem of when the choice might be ambiguous:

case x             # general 'switch'
when y then
...

What happens when y is a list; should it do x==y or x in y? (Or both?)

I haven't solved that yet but it's never come up. When x is anything 
other than an int, you invariably want an equality test.

-- 
Bartc

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


#104892

FromChris Angelico <rosuav@gmail.com>
Date2016-03-15 11:58 +1100
Message-ID<mailman.147.1458003523.12893.python-list@python.org>
In reply to#104889
On Tue, Mar 15, 2016 at 11:54 AM, BartC <bc@freeuk.com> wrote:
>> In Python, there's no reason to restrict 'switch'
>> to integers, so I would expect its semantics to be based on either
>> equality comparisons or inequality comparisons
>
>
> I use two forms of switch: one for integers only (very fast), and the other
> for any other values, which does tests in sequence.

I'm not sure what you gain by restricting to integers that you
couldn't also gain with other hashable types. Can you elaborate on
these optimizations?

ChrisA

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


#104896

FromBartC <bc@freeuk.com>
Date2016-03-15 01:22 +0000
Message-ID<nc7nuv$sgd$1@dont-email.me>
In reply to#104892
On 15/03/2016 00:58, Chris Angelico wrote:
> On Tue, Mar 15, 2016 at 11:54 AM, BartC <bc@freeuk.com> wrote:
>>> In Python, there's no reason to restrict 'switch'
>>> to integers, so I would expect its semantics to be based on either
>>> equality comparisons or inequality comparisons
>>
>>
>> I use two forms of switch: one for integers only (very fast), and the other
>> for any other values, which does tests in sequence.
>
> I'm not sure what you gain by restricting to integers that you
> couldn't also gain with other hashable types. Can you elaborate on
> these optimizations?

The integer-switch is intended for use with jump-tables, which requires 
not only that the case expressions are known at compile-time, but that 
they don't span too large a range.

(When a jump-table couldn't be used, then there was a slightly different 
implementation which scanned a list of the case-expressions. Linearly; a 
binary search or hash look-up could be done too, but this was in fast 
static code, not interpreted, so was not too critical. But I don't use 
this any more anyway.)

For use with Python, because constant expressions are going to be 
limited, such a switch would only work with case expressions that are 
numeric literals or character constants, which have to be written 
b"A"[0] iirc. So rather limited unless someone introduces named 
constants at the same time...

-- 
Bartc

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


#104905

FromChris Angelico <rosuav@gmail.com>
Date2016-03-15 13:02 +1100
Message-ID<mailman.149.1458007386.12893.python-list@python.org>
In reply to#104896
On Tue, Mar 15, 2016 at 12:22 PM, BartC <bc@freeuk.com> wrote:
> The integer-switch is intended for use with jump-tables, which requires not
> only that the case expressions are known at compile-time, but that they
> don't span too large a range.
>

Okay, which is what I mean by "compact". There'd be some lowest value
and some highest value, and the table has that many entries in it,
regardless of how many of them actually have meaningful information in
them.

With a hashtable, the values can be sparse. They would, however, still
need to be constant; otherwise it'd be hard to build the table in
advance.

ChrisA

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


Page 1 of 3  [1] 2 3  Next page →

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


csiph-web