Why no warnings when re-assigning builtin names?

Steven D'Aprano steve+comp.lang.python at pearwood.info
Wed Aug 17 02:58:41 CEST 2011


Seebs wrote:

> On 2011-08-16, Steven D'Aprano <steve+comp.lang.python at pearwood.info>
> wrote:
>> On Tue, 16 Aug 2011 01:23 pm Philip Semanchuk wrote:
>>>> Why should built-ins be treated as more sacred than your own objects?
>  
>>> Because built-ins are described in the official documentation as having
>>> a specific behavior, while my objects are not.
> 
>> *My* objects certainly are, because I write documentation for my code. My
>> docs are no less official than Python's docs.
> 
> Sure they are.  I can't get yours from python.org.

And what makes that unofficial? 

python.org is not the sole arbiter of official documentation in the world.
You can't get docs for Django or Scipy or NLTK from python.org either, but
just try telling the authors of those libraries that their docs are somehow
unofficial and see how far that gets you.


[...]
> I think code which shadows a built-in has a pretty real risk of being
> harmful at some unspecified future point when some maintainer who hasn't
> memorized every last line of the code makes the totally reasonable
> assumption that basic language features are still working and available.

Am I the only person who writes functions and methods any more? *wink*

Modern languages, and by modern I mean most languages more than, oh, about
fifty years old, provide ways to limit the scope of variables. You don't
need to memorise "every last line of the code" to safely edit a function.

def process(list, arg):
    spam(list)
    ham(arg)
    cheese(list, arg)

The scope of parameter "list" is limited to within the function process
itself. Inside, it shadows the built-in list. Outside, it doesn't do squat.


[...]
> My thoughts would be:
> 1.  It's hard to avoid shadowing anything unless you know the entire
> language and never forget things.

Define the "entire language". Does that include the names of all the
plethora of exceptions? How about the standard library?

For what it's worth, I don't care about memorising all the built-ins. I
delegate that job to my editor, which has a syntax highlighter for Python.
It never forgets built-ins. (In fact, sometimes this is a nuisance. When
I'm editing Python 3 code, it still insists that apply and reduce are
built-ins.)



> 2.  In particular, Python likes to use clear, obvious, names for things.
> Meaning that your choice of a clear, obvious, name for a similar thing
> could be the name of a thing in the language.

Yes, and Python also encourages the use of scopes, so that the clear,
obvious name for something in one scope does not clash with the clear,
obvious, identical name for something completely different in another
scope.


> 3.  I am not sure at all that shadowing can be "safe" in code which will
> some day be maintained.

Oh there's no doubt that shadowing *can* be unsafe. But then, very few
things can't be abused.

As I see it, there are (at least) four stages related to shadowing.

(1) At first, you don't even know enough to be concerned by shadowing. You
blithely call variables "list" and "str" without a care in the world...
until something goes wrong.


(2) Second stage, you know enough to realise that shadowing can be bad. You
avoid shadowing everything. Your code is full of variables called "my_list"
and "astr" and "some_tuple". You call your functions things like "izip"
even though it is designed as a replacement for zip, because the caller
might use from itertools import * and accidentally replace the built-in zip
with my zip. 

You even avoid using "string" as a variable name because it might shadow the
string module -- even though you haven't actually imported or used the
string module in the last four years.


(3) Eventually, you get frustrated writing doc strings like this:

    def function(astr, myint=0):
        """function(astr [, myint]) -> list

        Arguments:
        astr - string
        myint - integer

        Do something tool-like to a string and optional integer...
        """

and begin writing them like this:

    def function(astr, myint):
        """function(str [, int]) -> list

        Do something tool-like to a string and optional integer...
        """


(4) And then, after a while, you decide that perhaps shadowing is not always
so bad. (It helps if the Effbot tells you off for objecting to shadowing in
a two-line function.) At first, you limit yourself to using parameter names
that shadow built-ins in small tool-like functions. Then when the world
doesn't implode, you rethink the use of top-level function names
like "izip" and realise that namespaces exist so that you don't need to
care about shadowing functions you don't use, and if people call import *
they have nobody to blame but themselves if things break.



More-or-less-auto-biographically-ly y'rs,


-- 
Steven




More information about the Python-list mailing list