PyWart: Namespace asinitiy and the folly of the global statement

Discussion in 'Python' started by Rick Johnson, Feb 8, 2013.

  1. Rick Johnson

    Rick Johnson Guest

    Python's use of namespaces is, as we all quite know, "one honking great idea!"; and i must wholeheartedly agree, however, accessing and declaring variables living in python namespaces is a kludge at best, and a malevolent obfuscation at worst!

    ============================================================
    MODULE LEVEL VARIABLES
    ============================================================

    Take module level variables for example. When reading over some source codewe really have no idea in which namespace a variable lives. Consider the following:

    count = 0
    class Blah:
    def meth():
    for x in range(100):
    count = x

    Where is count living?

    Of course in this simplistic example we can see that count is @ module level, but what about a module with hundreds or even thousands of lines of code, multiple classes, multiple functions, constants out the yin-yang... yes that abomination Tkinter does comes to mind, but i digress... no one can be expected to remember every single variable MUCH LESS remember every variable's scope also, this is madness!

    ============================================================
    THE GLOBAL FOLLY
    ============================================================

    The global statement is not only useless but just serves to confuse people who have experience with languages that have "real" global variables -- notthat i am promoting the use of "real" global mind you, i find them to be the crutch of inexperienced programmers!

    In the "solution" section below i provide an outline of how to remove the global statement. I just want to rant about it here.

    ============================================================
    CLASS LEVEL AND INSTANCE LEVEL VARIABLES
    ============================================================

    There are two reasons why i just hate the manner in which python syntax forces me to create and accesses class level and instance level variables:

    1. class level variable creation requires
    no qualification whist access does!

    2. self is used confusingly for accessing
    both when self should only be used to
    access instance level variables!

    Consider this interactive session:

    >>> class Foo(object):

    cv = 0 # Class variable.
    def __init__(self):
    Foo.cv += 1
    print Foo.cv
    >>> f1 = Foo()

    1
    >>> f2 = Foo()

    2
    >>> f3 = Foo()

    3
    >>> ...


    So python will allow us to create a class level variable WITHOUT qualification however we must qualify the variable to modify it? Okay, okay, we couldinfer the scope from indention but what about consistency? I would prefer to qualify the variable in both cases! Besides, GvR had the Cojones to force us to write "self" as the first argument to EVERY SINGLE instance method under the justification of "self documenting code" when any sane person could intuit that "self" belongs to the INSTANCE only. Not to mention that Python has visual scoping in the form of forced indentation. GvR needs to answer for this crime against py-manity! But i digress!!!

    Oh, but just wait, the real strange stuff is just around the corner. Enter the twilight zone if you dare!

    >>> hasattr(Foo, 'cv')

    True

    Okay, i expected that but...

    >>> hasattr(f1, 'cv')

    True

    How the hell can an INSTANCE have an attribute named "cv" when "cv" is class level? Can you can hear the eery music?, can you see Rod's toothy grin?, I thought so!

    Hell, since we're already falling "head-over-heels" down the rabbit hole wemight as enjoy the visuals of a peep through the looking glass of insanity!

    >>> class Bar(object):

    cv = 0 # Class variable.
    def __init__(self):
    self.cv += 1
    print self.cv
    >>> b1 = Bar()

    1
    >>> b2 = Bar()

    1
    >>> b3 = Bar()

    1
    >>> ...


    Why did Python NOT throw an error? How could "self.cv" possibly execute when there is no instance variable named "cv"?

    ============================================================
    SOLUTION
    ============================================================

    It is my strong opinion that all "unqualified" variables must be local to the containing block, func/meth, class, or module. To access any variable outside of the local scope a programmer MUST qualify that variable with the func, class, or module identifiers. Consider the following examples

    # Module: example.py

    count = 0

    for x in range(100):
    # Increment the module level variable count.
    example.count += 1

    def increment():
    # Create a local variable named count.
    count = 0
    # Increment the module level variable named count.
    # No need for stupid global statement or guessing
    # because our code will be self documenting! (Then
    # Why the hell am i writing this comment! :p")
    example.count += 1
    # Create a new module level variable named foo
    example.foo = "foo"
    # return the local variable count.
    return count

    class Foo():
    # Declare a class level variable named "var". Must use
    # class identifier for both declaration and access!
    Foo.var = 0
    def __init__(self):
    # Increment the class level variable "var" by one. If
    # we had foolishly tried to access var using "self" we
    # have suffered the NameError.
    Foo.var += 1
    # If we want to assign variables at the instance level
    # we use self.
    self.var = "blah" # Instance variable

    *school-bell-rings*
     
    Rick Johnson, Feb 8, 2013
    #1
    1. Advertising

  2. On 02/07/2013 09:30 PM, Rick Johnson wrote:
    > count = 0
    > class Blah:
    > def meth():
    > for x in range(100):
    > count = x
    >
    > Where is count living?
    >
    > Of course in this simplistic example we can see that count is @
    > module level


    Except that it's not after the "count=x" statement inside the for loop.
    That's entirely within the local scope.

    Names bound to objects always default to the local namespace, whatever
    that is. If your function referred to "count" without any assignment,
    then it's unclear as to which namespace it is in. It could be the class
    namespace, or the module namespace. But that's a problem no different
    than in any language.

    Python does differ, from, say C, where global variables can be read and
    written to without any special declarations in a function, though you
    can tell at a glance whether or not a variable is declared in the local
    scope.
     
    Michael Torrie, Feb 8, 2013
    #2
    1. Advertising

  3. On Fri, Feb 8, 2013 at 3:30 PM, Rick Johnson
    <> wrote:
    > It is my strong opinion that all "unqualified" variables must be local tothe containing block, func/meth, class, or module. To access any variable outside of the local scope a programmer MUST qualify that variable with thefunc, class, or module identifiers. Consider the following examples


    Okay. Now start actually working with things, instead of just making
    toys. All your builtins now need to be qualified:

    __builtins__.print("There
    are",__builtins__.len(self.some_list),"members in this list,
    namely:",__builtins__.repr(self.some_list))

    And your imports happen at module level, so they need extra qualification:

    # file: example.py

    import sys

    def foo():
    __builtins__.print("My args were:",example.sys.argv)

    Actually, you already ran up against this. Your example needs to become:

    for x in __builtins__.range(100):
    # Increment the module level variable count.
    example.count += 1

    Or are you going to make builtins and imports magically available as
    PHP-style superglobals?

    ChrisA
     
    Chris Angelico, Feb 8, 2013
    #3
  4. Rick Johnson

    Rick Johnson Guest

    On Friday, February 8, 2013 12:25:34 AM UTC-6, Chris Angelico wrote:
    > On Fri, Feb 8, 2013 at 3:30 PM, Rick Johnson wrote:
    > > It is my strong opinion that all "unqualified" variables must be local to the containing block, func/meth, class, or module. To access any variable outside of the local scope a programmer MUST qualify that variable with the func, class, or module identifiers. Consider the following examples

    >
    > Okay. Now start actually working with things, instead of just making
    > toys. All your builtins now need to be qualified:


    Chris you are very trollish, and a total tool of Deaprano, but you are damnfunny sometimes and for that reason i still respond to you. ;-)

    > __builtins__.print("There
    > are",__builtins__.len(self.some_list),"members in this list,
    > namely:",__builtins__.repr(self.some_list))


    That's funny, and i laughed whilst reading it, but i do have to admit that i did not explain this detail. IMHO, all builtins should not be auto-imported, the programmer should import them either on a case by case basis, or dothe global import:

    from builtins import print, len, repr
    from builtins import * # This is not recommended!

    This would serve two purposes (1) the reader would know which builtins where being used in this module (2) the names would be bound properly to the module namespace. But this does not answer your question, merely a side note

    So your assertion is wrong. Built-ins /would/ be available at the module level with no qualification just as they are now. But they would also be available in /every/ namespace because how else would we use them Chris?

    It's very simple, when python encounters a unqualified symbol, it looks first for a match in the built-in symbols array, and if not match is found it then raises a NameError.

    > Or are you going to make builtins and imports magically available as
    > PHP-style superglobals?


    Hmm, what are they now Chris? Python built-ins are known everywhere withoutqualification and require no import. I think super-global about sums it up..
     
    Rick Johnson, Feb 8, 2013
    #4
  5. Rick Johnson

    Rick Johnson Guest

    On Friday, February 8, 2013 12:25:34 AM UTC-6, Chris Angelico wrote:
    > On Fri, Feb 8, 2013 at 3:30 PM, Rick Johnson wrote:
    > > It is my strong opinion that all "unqualified" variables must be local to the containing block, func/meth, class, or module. To access any variable outside of the local scope a programmer MUST qualify that variable with the func, class, or module identifiers. Consider the following examples

    >
    > Okay. Now start actually working with things, instead of just making
    > toys. All your builtins now need to be qualified:


    Chris you are very trollish, and a total tool of Deaprano, but you are damnfunny sometimes and for that reason i still respond to you. ;-)

    > __builtins__.print("There
    > are",__builtins__.len(self.some_list),"members in this list,
    > namely:",__builtins__.repr(self.some_list))


    That's funny, and i laughed whilst reading it, but i do have to admit that i did not explain this detail. IMHO, all builtins should not be auto-imported, the programmer should import them either on a case by case basis, or dothe global import:

    from builtins import print, len, repr
    from builtins import * # This is not recommended!

    This would serve two purposes (1) the reader would know which builtins where being used in this module (2) the names would be bound properly to the module namespace. But this does not answer your question, merely a side note

    So your assertion is wrong. Built-ins /would/ be available at the module level with no qualification just as they are now. But they would also be available in /every/ namespace because how else would we use them Chris?

    It's very simple, when python encounters a unqualified symbol, it looks first for a match in the built-in symbols array, and if not match is found it then raises a NameError.

    > Or are you going to make builtins and imports magically available as
    > PHP-style superglobals?


    Hmm, what are they now Chris? Python built-ins are known everywhere withoutqualification and require no import. I think super-global about sums it up..
     
    Rick Johnson, Feb 8, 2013
    #5
  6. On Fri, Feb 8, 2013 at 6:23 PM, Rick Johnson
    <> wrote:
    > from builtins import print, len, repr
    > from builtins import * # This is not recommended!
    >
    > This would serve two purposes (1) the reader would know which builtins where being used in this module (2) the names would be bound properly to the module namespace. But this does not answer your question, merely a side note
    >
    > So your assertion is wrong. Built-ins /would/ be available at the module level with no qualification just as they are now. But they would also be available in /every/ namespace because how else would we use them Chris?


    So what you're saying is that builtins are available without
    qualification inside a function, but other names imported into the
    module namespace aren't? MAGIC.

    ChrisA
     
    Chris Angelico, Feb 8, 2013
    #6
  7. Chris Angelico wrote:

    > On Fri, Feb 8, 2013 at 3:30 PM, Rick Johnson
    > <> wrote:
    >> It is my strong opinion that all "unqualified" variables must be local to
    >> the containing block, func/meth, class, or module. To access any variable
    >> outside of the local scope a programmer MUST qualify that variable with
    >> the func, class, or module identifiers. Consider the following examples

    >
    > Okay. Now start actually working with things, instead of just making
    > toys. All your builtins now need to be qualified:
    >
    > __builtins__.print("There
    > are",__builtins__.len(self.some_list),"members in this list,
    > namely:",__builtins__.repr(self.some_list))



    Pardon me, but since __builtins__ is a global, you have to say:

    globals.__builtins__.print("screw this for a game of soldiers")

    or equivalent.


    --
    Steven
     
    Steven D'Aprano, Feb 8, 2013
    #7
  8. On Fri, Feb 8, 2013 at 10:29 PM, Steven D'Aprano
    <> wrote:
    > Chris Angelico wrote:
    >
    >> On Fri, Feb 8, 2013 at 3:30 PM, Rick Johnson
    >> <> wrote:
    >>> It is my strong opinion that all "unqualified" variables must be local to
    >>> the containing block, func/meth, class, or module. To access any variable
    >>> outside of the local scope a programmer MUST qualify that variable with
    >>> the func, class, or module identifiers. Consider the following examples

    >>
    >> Okay. Now start actually working with things, instead of just making
    >> toys. All your builtins now need to be qualified:
    >>
    >> __builtins__.print("There
    >> are",__builtins__.len(self.some_list),"members in this list,
    >> namely:",__builtins__.repr(self.some_list))

    >
    >
    > Pardon me, but since __builtins__ is a global, you have to say:
    >
    > globals.__builtins__.print("screw this for a game of soldiers")
    >
    > or equivalent.


    And isn't globals a builtin?

    ChrisA
     
    Chris Angelico, Feb 8, 2013
    #8
  9. Rick Johnson wrote:

    > When reading over some source code we really have no idea in which
    > namespace a variable lives. Consider the following:
    >
    > count = 0
    > class Blah:
    > def meth():
    > for x in range(100):
    > count = x
    >
    > Where is count living?
    >
    > Of course in this simplistic example we can see that count is @ module
    > level


    But it isn't. It is a local variable.

    Rick, I appreciate your honesty in telling us that you have no idea how to
    read Python code and recognise which namespace the variables are found in,
    but you really shouldn't assume others suffer under that same affliction.



    --
    Steven
     
    Steven D'Aprano, Feb 8, 2013
    #9
  10. On 02/08/2013 04:45 AM, Steven D'Aprano wrote:
    > Rick Johnson wrote:
    >> Of course in this simplistic example we can see that count is @ module
    >> level

    >
    > But it isn't. It is a local variable.
    >
    > Rick, I appreciate your honesty in telling us that you have no idea how to
    > read Python code and recognise which namespace the variables are found in,
    > but you really shouldn't assume others suffer under that same affliction.


    Very interesting to hear the crickets chirping over this one as the
    trolling continues on another thread. Rick seems to know his stuff
    about Tk programming, but his knowledge of programming language theory
    and formal computing seems quite informal.
     
    Michael Torrie, Feb 9, 2013
    #10
  11. Rick Johnson

    alex23 Guest

    On Feb 9, 2:25 pm, Michael Torrie <> wrote:
    > Rick seems to know his stuff
    > about Tk programming, but his knowledge of programming language theory
    > and formal computing seems quite informal.


    Not informal, "intuited". If he doesn't already know something, it's
    apparently not important.
     
    alex23, Feb 11, 2013
    #11
  12. On Mon, Feb 11, 2013 at 1:42 PM, alex23 <> wrote:
    > On Feb 9, 2:25 pm, Michael Torrie <> wrote:
    >> Rick seems to know his stuff
    >> about Tk programming, but his knowledge of programming language theory
    >> and formal computing seems quite informal.

    >
    > Not informal, "intuited". If he doesn't already know something, it's
    > apparently not important.


    I wonder how he learned about Tk. To be quite frank, I've not found
    tkinter to be particularly intuitive, and I've been doing GUI
    programming since the early 90s (with a wide variety of toolkits).
    Mind, that's not necessarily an indictment of tkinter per se; MOST
    windowing toolkits take a bit of mastering. But my general estimate is
    that it takes roughly as long to learn a GUI toolkit as to learn a
    language, and takes comparable effort.

    ChrisA
     
    Chris Angelico, Feb 11, 2013
    #12
  13. Rick Johnson

    Jason Swails Guest

    On Mon, Feb 11, 2013 at 1:27 AM, Chris Angelico <> wrote:

    > On Mon, Feb 11, 2013 at 1:42 PM, alex23 <> wrote:
    > > On Feb 9, 2:25 pm, Michael Torrie <> wrote:
    > >> Rick seems to know his stuff
    > >> about Tk programming, but his knowledge of programming language theory
    > >> and formal computing seems quite informal.

    > >
    > > Not informal, "intuited". If he doesn't already know something, it's
    > > apparently not important.

    >
    > I wonder how he learned about Tk. To be quite frank, I've not found
    > tkinter to be particularly intuitive, and I've been doing GUI
    > programming since the early 90s (with a wide variety of toolkits).
    >


    Perhaps that's your problem ;). Tkinter was the first--and only--GUI
    toolkit I learned [1] (I do almost exclusively CLI, and GUI only for fun --
    and I program as a result of the work I do). Having no previous knowledge
    of any other GUI toolkit (and really only writing 2 or 3 _real_ GUIs
    total), it wasn't hard to pick up enough from effbot/stackoverflow/tkinter
    documentation to get a working GUI with (what I think is) decent code
    organization.

    Just my personal experience.

    --Jason

    [1] Tkinter is part of the stdlib, and I try to minimize external
    dependencies
     
    Jason Swails, Feb 11, 2013
    #13
  14. On 02/11/2013 11:32 AM, Jason Swails wrote:
    >
    > Perhaps that's your problem ;). Tkinter was the first--and only--GUI
    > toolkit I learned [1] (I do almost exclusively CLI, and GUI only for fun --
    > and I program as a result of the work I do). Having no previous knowledge
    > of any other GUI toolkit (and really only writing 2 or 3 _real_ GUIs
    > total), it wasn't hard to pick up enough from effbot/stackoverflow/tkinter
    > documentation to get a working GUI with (what I think is) decent code
    > organization.
    >
    > Just my personal experience.


    My first experience with GUI programming was with MFC on windows. Yuck!
    Anything is better. Although wxWidgets seems to follow the MFC model
    in some ways, and that has always left a sour taste in my mouth.

    Since then I've done both GTK and Qt programming and both are a
    pleasure, especially in Python.
     
    Michael Torrie, Feb 11, 2013
    #14
  15. On Tue, Feb 12, 2013 at 6:15 AM, Michael Torrie <> wrote:
    > On 02/11/2013 11:32 AM, Jason Swails wrote:
    >>
    >> Perhaps that's your problem ;). Tkinter was the first--and only--GUI
    >> toolkit I learned [1] (I do almost exclusively CLI, and GUI only for fun --
    >> and I program as a result of the work I do). Having no previous knowledge
    >> of any other GUI toolkit (and really only writing 2 or 3 _real_ GUIs
    >> total), it wasn't hard to pick up enough from effbot/stackoverflow/tkinter
    >> documentation to get a working GUI with (what I think is) decent code
    >> organization.
    >>
    >> Just my personal experience.

    >
    > My first experience with GUI programming was with MFC on windows. Yuck!
    > Anything is better. Although wxWidgets seems to follow the MFC model
    > in some ways, and that has always left a sour taste in my mouth.
    >
    > Since then I've done both GTK and Qt programming and both are a
    > pleasure, especially in Python.


    Lately I've done all my GUI work with GTK, and it's worked out nicely
    for me. But I still assume that it'll take as long to learn as the
    language I'm using - which, for good languages like Python, isn't all
    that long, but it's not like mastering urllib.

    ChrisA
     
    Chris Angelico, Feb 11, 2013
    #15
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. rantingrick
    Replies:
    20
    Views:
    496
    Terry Reedy
    Jul 23, 2011
  2. rantingrick
    Replies:
    0
    Views:
    187
    rantingrick
    Jul 22, 2011
  3. Rick Johnson
    Replies:
    0
    Views:
    116
    Rick Johnson
    Feb 18, 2013
  4. Terry Reedy
    Replies:
    2
    Views:
    125
    Terry Reedy
    Feb 19, 2013
  5. Rick Johnson
    Replies:
    21
    Views:
    129
    Ian Kelly
    Feb 13, 2014
Loading...

Share This Page