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


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

Re: "Don't rebind built-in names*" - it confuses readers

Started byMark Janssen <dreamingforward@gmail.com>
First post2013-06-10 17:18 -0700
Last post2013-06-13 10:28 +1000
Articles 12 — 6 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: "Don't rebind built-in names*" - it confuses readers Mark Janssen <dreamingforward@gmail.com> - 2013-06-10 17:18 -0700
    Re: "Don't rebind built-in names*" - it confuses readers Grant Edwards <invalid@invalid.invalid> - 2013-06-12 14:24 +0000
      Re: "Don't rebind built-in names*" - it confuses readers Mark Janssen <dreamingforward@gmail.com> - 2013-06-12 12:40 -0700
      Re: "Don't rebind built-in names*" - it confuses readers Chris Angelico <rosuav@gmail.com> - 2013-06-13 06:30 +1000
      Re: "Don't rebind built-in names*" - it confuses readers Mark Janssen <dreamingforward@gmail.com> - 2013-06-12 16:07 -0700
      Re: "Don't rebind built-in names*" - it confuses readers Chris Angelico <rosuav@gmail.com> - 2013-06-13 09:53 +1000
        Re: "Don't rebind built-in names*" - it confuses readers Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-06-13 00:47 +0000
      Re: "Don't rebind built-in names*" - it confuses readers Skip Montanaro <skip@pobox.com> - 2013-06-12 19:06 -0500
      Re: "Don't rebind built-in names*" - it confuses readers Mark Janssen <dreamingforward@gmail.com> - 2013-06-12 17:26 -0700
        Re: "Don't rebind built-in names*" - it confuses readers Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-06-13 01:23 +0000
          Re: "Don't rebind built-in names*" - it confuses readers Nobody <nobody@nowhere.com> - 2013-06-13 11:09 +0100
      Re: "Don't rebind built-in names*" - it confuses readers Chris Angelico <rosuav@gmail.com> - 2013-06-13 10:28 +1000

#47792 — Re: "Don't rebind built-in names*" - it confuses readers

FromMark Janssen <dreamingforward@gmail.com>
Date2013-06-10 17:18 -0700
SubjectRe: "Don't rebind built-in names*" - it confuses readers
Message-ID<mailman.3096.1371040064.3114.python-list@python.org>
>         list = []
> Reading further, one sees that the function works with two lists, a list of
> file names, unfortunately called 'list',

That is very good advice in general:  never choose a variable name
that is a keyword.
-- 
MarkJ
Tacoma, Washington

[toc] | [next] | [standalone]


#47805

FromGrant Edwards <invalid@invalid.invalid>
Date2013-06-12 14:24 +0000
Message-ID<kpa0ae$b4t$1@reader1.panix.com>
In reply to#47792
On 2013-06-11, Mark Janssen <dreamingforward@gmail.com> wrote:
>>         list = []
>> Reading further, one sees that the function works with two lists, a list of
>> file names, unfortunately called 'list',
>
> That is very good advice in general:  never choose a variable name
> that is a keyword.

You can't choose a vriable name that is a keyword: the compiler won't
allow it.

"list" isn't a keyword.

-- 
Grant Edwards               grant.b.edwards        Yow! Maybe I should have
                                  at               asked for my Neutron Bomb
                              gmail.com            in PAISLEY --

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


#47833

FromMark Janssen <dreamingforward@gmail.com>
Date2013-06-12 12:40 -0700
Message-ID<mailman.3121.1371066032.3114.python-list@python.org>
In reply to#47805
On Wed, Jun 12, 2013 at 7:24 AM, Grant Edwards <invalid@invalid.invalid> wrote:
> On 2013-06-11, Mark Janssen <dreamingforward@gmail.com> wrote:
>>>         list = []
>>> Reading further, one sees that the function works with two lists, a list of
>>> file names, unfortunately called 'list',
>>
>> That is very good advice in general:  never choose a variable name
>> that is a keyword.
>
> You can't choose a vriable name that is a keyword: the compiler won't
> allow it.
>
> "list" isn't a keyword.

You're right.  I was being sloppy.
-- 
MarkJ
Tacoma, Washington

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


#47845

FromChris Angelico <rosuav@gmail.com>
Date2013-06-13 06:30 +1000
Message-ID<mailman.3128.1371069023.3114.python-list@python.org>
In reply to#47805
On Thu, Jun 13, 2013 at 5:40 AM, Mark Janssen <dreamingforward@gmail.com> wrote:
> On Wed, Jun 12, 2013 at 7:24 AM, Grant Edwards <invalid@invalid.invalid> wrote:
>> On 2013-06-11, Mark Janssen <dreamingforward@gmail.com> wrote:
>>>>         list = []
>>>> Reading further, one sees that the function works with two lists, a list of
>>>> file names, unfortunately called 'list',
>>>
>>> That is very good advice in general:  never choose a variable name
>>> that is a keyword.
>>
>> You can't choose a vriable name that is a keyword: the compiler won't
>> allow it.
>>
>> "list" isn't a keyword.
>
> You're right.  I was being sloppy.

We're talking about builtins, and unfortunately there are... well, let
me ask Thespis, from the play of the same name:

Thespis: Oh, then I suppose there are some complaints?
Mercury: Yes, there are some.
Thespis (disturbed): Oh, perhaps there are a good many?
Mercury: There are a good many.
Thespis: Oh, perhaps there are a thundering lot?
Mercury: There are a thundering lot.
Thespis (very much disturbed): Oh.

>>> dir(__builtins__)
['ArithmeticError', 'AssertionError', 'AttributeError',
'BaseException', 'BlockingIOError', 'BrokenPipeError', 'BufferError',
'BytesWarning', 'ChildProcessError', 'ConnectionAbortedError',
'ConnectionError', 'ConnectionRefusedError', 'ConnectionResetError',
'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError',
'Exception', 'False', 'FileExistsError', 'FileNotFoundError',
'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError',
'ImportError', 'ImportWarning', 'IndentationError', 'IndexError',
'InterruptedError', 'IsADirectoryError', 'KeyError',
'KeyboardInterrupt', 'LookupError', 'MemoryError', 'NameError',
'None', 'NotADirectoryError', 'NotImplemented', 'NotImplementedError',
'OSError', 'OverflowError', 'PendingDeprecationWarning',
'PermissionError', 'ProcessLookupError', 'ReferenceError',
'ResourceWarning', 'RuntimeError', 'RuntimeWarning', 'StopIteration',
'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit',
'TabError', 'TimeoutError', 'True', 'TypeError', 'UnboundLocalError',
'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError',
'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning',
'ValueError', 'Warning', 'WindowsError', 'ZeroDivisionError', '_',
'__build_class__', '__debug__', '__doc__', '__import__', '__name__',
'__package__', 'abs', 'all', 'any', 'ascii', 'bin', 'bool',
'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'compile',
'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod',
'enumerate', 'eval', 'exec', 'exit', 'filter', 'float', 'format',
'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex',
'id', 'input', 'int', 'isinstance', 'issubclass', 'iter', 'len',
'license', 'list', 'locals', 'map', 'max', 'memoryview', 'min',
'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property',
'quit', 'range', 'repr', 'reversed', 'round', 'set', 'setattr',
'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple',
'type', 'vars', 'zip']

I think I can safely say that all the names beginning with an
uppercase letter (exceptions, True/False/None/Ellipsis), and the ones
beginning with underscores, should not be overridden. Well and good.
Still leaves 72 builtins. Obviously overriding len, print, range, etc
would be risky (unless, as mentioned above, you're making a drop-in
replacement), but there are plenty that you'd never notice (eg if you
use "hash" for an encoded password, or "input" for the string the user
typed into an HTML form). I would hope, for instance, that an editor
would not color-highlight 'credits' differently, as it's designed for
interactive work. There are plenty in the grey area - is it safe to
use "sum" as an accumulator or "min" for a unit of time? What about
using "super" to store the amount of retirement money you've put away?
I'd be inclined to avoid this sort any time I'm aware of them, just
because it'll make debugging easier on the day when something goes
wrong.

ChrisA

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


#47856

FromMark Janssen <dreamingforward@gmail.com>
Date2013-06-12 16:07 -0700
Message-ID<mailman.3137.1371078442.3114.python-list@python.org>
In reply to#47805
>> You're right.  I was being sloppy.
>
> ['ArithmeticError', 'AssertionError', 'AttributeError',
> 'BaseException', 'BlockingIOError', 'BrokenPipeError', 'BufferError',
> 'BytesWarning', 'ChildProcessError', 'ConnectionAbortedError',
> 'ConnectionError', 'ConnectionRefusedError', 'ConnectionResetError',
> 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError',
> 'Exception', 'False', 'FileExistsError', 'FileNotFoundError',
> 'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError',
> 'ImportError', 'ImportWarning', 'IndentationError', 'IndexError',
> 'InterruptedError', 'IsADirectoryError', 'KeyError',
> 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'NameError',
> 'None', 'NotADirectoryError', 'NotImplemented', 'NotImplementedError',
> 'OSError', 'OverflowError', 'PendingDeprecationWarning',
> 'PermissionError', 'ProcessLookupError', 'ReferenceError',
> 'ResourceWarning', 'RuntimeError', 'RuntimeWarning', 'StopIteration',
> 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit',
> 'TabError', 'TimeoutError', 'True', 'TypeError', 'UnboundLocalError',
> 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError',
> 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning',
> 'ValueError', 'Warning', 'WindowsError', 'ZeroDivisionError', '_',
> '__build_class__', '__debug__', '__doc__', '__import__', '__name__',
> '__package__', 'abs', 'all', 'any', 'ascii', 'bin', 'bool',
> 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'compile',
> 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod',
> 'enumerate', 'eval', 'exec', 'exit', 'filter', 'float', 'format',
> 'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex',
> 'id', 'input', 'int', 'isinstance', 'issubclass', 'iter', 'len',
> 'license', 'list', 'locals', 'map', 'max', 'memoryview', 'min',
> 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property',
> 'quit', 'range', 'repr', 'reversed', 'round', 'set', 'setattr',
> 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple',
> 'type', 'vars', 'zip']
>
> I think I can safely say that all the names beginning with an
> uppercase letter (exceptions, True/False/None/Ellipsis), and the ones
> beginning with underscores, should not be overridden. Well and good.
> Still leaves 72 builtins. Obviously overriding len, print, range, etc
> would be risky (unless, as mentioned above, you're making a drop-in
> replacement), but there are plenty that you'd never notice (eg if you
> use "hash" for an encoded password, or "input" for the string the user
> typed into an HTML form). I would hope, for instance, that an editor
> would not color-highlight 'credits' differently, as it's designed for
> interactive work. There are plenty in the grey area - is it safe to
> use "sum" as an accumulator or "min" for a unit of time? What about
> using "super" to store the amount of retirement money you've put away?
> I'd be inclined to avoid this sort any time I'm aware of them, just
> because it'll make debugging easier on the day when something goes
> wrong.

Okay, now I'm a bit confused.  "print" is both a <keyword> and a
member of the builtins.  What happens then?

And abs(), max(), hex()  and such seemed like keywords to my
scientific self (due to never having to "include"/import them), but
clearly their not.  And int, list, tuple, dict and such always seemed
like keywords to my CS self because they were included in Python's
type system (like "int" would be in C).

They are all one-step removed from keywords.   And yet, since they are
not in a separate namespace, they should not be used as variable
names.  Perhaps since they are very different from one another, they
should be put in separate namespaces off of a global, root
namespace...  (math, string, etc.)

Despite that, seems like PEP8 should suggest this not shadowing these
built-ins which are at global scope.

MarkJ
Tacoma, Washington

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


#47861

FromChris Angelico <rosuav@gmail.com>
Date2013-06-13 09:53 +1000
Message-ID<mailman.3141.1371081214.3114.python-list@python.org>
In reply to#47805
On Thu, Jun 13, 2013 at 9:07 AM, Mark Janssen <dreamingforward@gmail.com> wrote:
>>> You're right.  I was being sloppy.
> Okay, now I'm a bit confused.  "print" is both a <keyword> and a
> member of the builtins.  What happens then?

Ah! I see where we are getting confused. When you said keyword, did
you mean keyword, a person who has lost his parents... oops, that's
Pirates of Penzance. Ahem.

In Python 2.x, 'print' is actually a keyword. It has its own special
syntax (eg printing to something other than stdout), and absolutely
cannot be overridden:

Python 2.7.4 (default, Apr  6 2013, 19:54:46) [MSC v.1500 32 bit
(Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> print=1
  File "<stdin>", line 1
    print=1
         ^
SyntaxError: invalid syntax

But in Python 3, it's a builtin function:

Python 3.3.0 (v3.3.0:bd8afb90ebf2, Sep 29 2012, 10:55:48) [MSC v.1600 32 bit (In
tel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> foo=print
>>> print=1
>>> foo("Hello, world!")
Hello, world!

> And abs(), max(), hex()  and such seemed like keywords to my
> scientific self (due to never having to "include"/import them), but
> clearly their not.

The builtins don't need to be imported, but they're identifiers like
anything else. They're a namespace that gets searched after
module-globals.

int = 1
def foo():
   int = 2
   print(int)

This has double shadowing :) It'll print 2, because locals get
searched first, but if you remove that assignment then it'll print 1,
and if you remove _that_ one, then it'll print "<class 'int'>".
There's nothing magical about the name int, but before raising
NameError, the interpreter will look for it in builtins. You can even
add more "builtins", though I would *strongly* advise against this
unless you have a really REALLY good reason:

>>> __builtins__.helloworld=123
>>> helloworld
123
>>> helloworld=234
>>> helloworld
234
>>> del helloworld
>>> helloworld
123

> And int, list, tuple, dict and such always seemed
> like keywords to my CS self because they were included in Python's
> type system (like "int" would be in C).

Yep, but in Python, types/classes are themselves objects, so you can
pass them around like anything else. This also downgrades them from
"language keyword" to "always-available name", which in effect
upgrades your _own_ classes to the same level.

> They are all one-step removed from keywords.   And yet, since they are
> not in a separate namespace, they should not be used as variable
> names.  Perhaps since they are very different from one another, they
> should be put in separate namespaces off of a global, root
> namespace...  (math, string, etc.)

There's no point forcing them to be looked up in a two-step process.
If you want that, you can simply reference them as
__builtins__.whatever, but you can instead just reference them as the
unadorned name whatever. They contribute heavily to the simplicity and
readability of Python code - imagine if every call to len() had to be
qualified.

ChrisA

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


#47873

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2013-06-13 00:47 +0000
Message-ID<51b916bf$0$29997$c3e8da3$5496439d@news.astraweb.com>
In reply to#47861
On Thu, 13 Jun 2013 09:53:26 +1000, Chris Angelico wrote:

> In Python 2.x, 'print' is actually a keyword. It has its own special
> syntax (eg printing to something other than stdout), and absolutely
> cannot be overridden:

Except that you can:

from __future__ import print_function

Just to make things complicated :-)



-- 
Steven

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


#47864

FromSkip Montanaro <skip@pobox.com>
Date2013-06-12 19:06 -0500
Message-ID<mailman.3144.1371081976.3114.python-list@python.org>
In reply to#47805
> Okay, now I'm a bit confused.  "print" is both a <keyword> and a
> member of the builtins.  What happens then?

It's a keyword in Python < 3, a built-in function in Python >= 3:

~% python3
Python 3.4.0a0 (default:96f08a22f562, Feb 24 2013, 23:37:53)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> print
<built-in function print>
>>> x = print
>>>
~% python2
Python 2.7.5+ (2.7:4657d0eebe42, Jun  2 2013, 07:46:59)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> print

>>> x = print
  File "<stdin>", line 1
    x = print
            ^
SyntaxError: invalid syntax


Skip

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


#47870

FromMark Janssen <dreamingforward@gmail.com>
Date2013-06-12 17:26 -0700
Message-ID<mailman.3147.1371083212.3114.python-list@python.org>
In reply to#47805
> The builtins don't need to be imported, but they're identifiers like
> anything else. They're a namespace that gets searched after
> module-globals.

Yes, I understand, though for clarity and separability, it seems that
having them in a namespace that gets explicitly pulled into the global
space is less messy, despite the extra step (the default python
distribution could include a STARTUP file that imports the builtin
types).  But I must withhold my personal philosophy lest it get too
complicated.

>> And int, list, tuple, dict and such always seemed
>> like keywords to my CS self because they were included in Python's
>> type system (like "int" would be in C).
>
> Yep, but in Python, types/classes are themselves objects, so you can
> pass them around like anything else. This also downgrades them from
> "language keyword" to "always-available name", which in effect
> upgrades your _own_ classes to the same level.

Yes, and here is where I've been trying to argue that Python's object
model isn't right.  But I must abstain from commenting further.

>> They are all one-step removed from keywords.   And yet, since they are
>> not in a separate namespace, they should not be used as variable
>> names.  Perhaps since they are very different from one another, they
>> should be put in separate namespaces off of a global, root
>> namespace...  (math, string, etc.)
>
> There's no point forcing them to be looked up in a two-step process.
> If you want that, you can simply reference them as
> __builtins__.whatever, but you can instead just reference them as the
> unadorned name whatever. They contribute heavily to the simplicity and
> readability of Python code - imagine if every call to len() had to be
> qualified.

Well I would anticipate a keyword ("load"?) so one could load a
particular namespace into the global scope.  The issue I guess is when
should modules be "on file" vs. "in memory" like the builtins?  The
reason this is coming up, is because I would like to imagine a data
ecosystem, where I can import a set of objects from the network as if
they are local right into my interpreter environment.

-- 
MarkJ
Tacoma, Washington

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


#47878

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2013-06-13 01:23 +0000
Message-ID<51b91f0f$0$29997$c3e8da3$5496439d@news.astraweb.com>
In reply to#47870
On Wed, 12 Jun 2013 17:26:43 -0700, Mark Janssen wrote:

>> The builtins don't need to be imported, but they're identifiers like
>> anything else. They're a namespace that gets searched after
>> module-globals.
> 
> Yes, I understand, though for clarity and separability, it seems that
> having them in a namespace that gets explicitly pulled into the global
> space is less messy, despite the extra step (the default python
> distribution could include a STARTUP file that imports the builtin
> types).

No. Having a separate builtin namespace is a design feature. 

In Python, every module has it's own global namespace. Within module X, 
globals() is dfferent from within module Y. (So it's not really globally-
global, it's only locally-global, if you like.) This is a Very Good Thing 
-- it means that each module is compartmentalised away from every other, 
by default.

Python does have a globally-global namespace. It is called "builtins", 
and you're not supposed to touch it. Of course, being Python, you can if 
you want, but if you do, you are responsible for whatever toes you shoot 
off.

Modifying builtins will effect *all modules*. That's normally too much, 
although it can very, very, very occasionally be useful. Especially in 
testing and debugging. But a module can *shadow* the builtins, by simply 
defining a name that matches a builtin name, without affecting any other 
module. So for example, the re module defines a function compile, which 
shadows the built-in compile, but:

- the re module doesn't use the built-in compile

- other modules normally use the fully-qualified re.compile

so, in practice, there is no conflict.



-- 
Steven

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


#47932

FromNobody <nobody@nowhere.com>
Date2013-06-13 11:09 +0100
Message-ID<pan.2013.06.13.10.09.28.882000@nowhere.com>
In reply to#47878
On Thu, 13 Jun 2013 01:23:27 +0000, Steven D'Aprano wrote:

> Python does have a globally-global namespace. It is called "builtins", and
> you're not supposed to touch it. Of course, being Python, you can if you
> want, but if you do, you are responsible for whatever toes you shoot off.
> 
> Modifying builtins will effect *all modules*. That's normally too much,
> although it can very, very, very occasionally be useful.

For a specific example, gettext.install() adds the _() function to the
builtins namespace.

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


#47871

FromChris Angelico <rosuav@gmail.com>
Date2013-06-13 10:28 +1000
Message-ID<mailman.3148.1371083315.3114.python-list@python.org>
In reply to#47805
On Thu, Jun 13, 2013 at 10:26 AM, Mark Janssen
<dreamingforward@gmail.com> wrote:
>> There's no point forcing them to be looked up in a two-step process.
>> If you want that, you can simply reference them as
>> __builtins__.whatever, but you can instead just reference them as the
>> unadorned name whatever. They contribute heavily to the simplicity and
>> readability of Python code - imagine if every call to len() had to be
>> qualified.
>
> Well I would anticipate a keyword ("load"?) so one could load a
> particular namespace into the global scope.  The issue I guess is when
> should modules be "on file" vs. "in memory" like the builtins?  The
> reason this is coming up, is because I would like to imagine a data
> ecosystem, where I can import a set of objects from the network as if
> they are local right into my interpreter environment.

The syntax you describe is effectively:

from __builtins__ import *

ChrisA

[toc] | [prev] | [standalone]


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


csiph-web