Anyone ever overridden a builtin by accident?

J

John Ladasky

Hi there,

Just wanted to share a frustrating programming bug that, when I
figured it out, made me gasp, and then laugh.

In one of my programs I wrote...

c = max(a,b)

....and I was getting the most annoying, frustrating error message:
"type 'int' is not callable."

What the heck? I wasn't calling an integer, I was calling the
__builtin__ function, max()!

I dropped out of my regular editor (SciTE), opened IDLE, and tried
typing in bits of my code, including the call to max(). Everything
seemed to work fine.

Then, I finally spotted the problem. At the beginning of my program I
had defined a variable called "max"! I had overridden the __builtin__
function by mistake.

Is there ever a good reason to override something in __builtin__?
It's powerful, but potentially quite confusing. Can the interpreter
be instructed to give a warning message when you do it?

Yes indeed, *everything* in Python is an object. Let the newbie
beware!

--
John J. Ladasky Jr., Ph.D.
Department of Biology
Johns Hopkins University
Baltimore MD 21218
USA
Earth
 
L

Lulu of the Lotus-Eaters

|I had overridden the __builtin__ function by mistake.

I had a script or two that used 'dict' as a variable name... which was
fine, until Python 2.2. Since then, I've used 'dct' for the same
purpose. But possibly something old is still sitting around with the
problem.

Yours, Lulu...
 
R

Robin Becker

John said:
Hi there,

Just wanted to share a frustrating programming bug that, when I
figured it out, made me gasp, and then laugh. .......

Then, I finally spotted the problem. At the beginning of my program I
had defined a variable called "max"! I had overridden the __builtin__
function by mistake.

Is there ever a good reason to override something in __builtin__?
It's powerful, but potentially quite confusing. Can the interpreter
be instructed to give a warning message when you do it?
I'm sure there are reasons why builtin classes/objects/methods might
need to be overridden, but I think it should perhaps be a bit more
difficult.

I believe there is an intention to make this harder than it currently
is. There is some effort made into making shadowing of module globals
hard (to allow some code optimisations I guess) builtins are also sort
of global so perhaps the same restrictions should apply.
 
J

John Roth

John Ladasky said:
Hi there,

Just wanted to share a frustrating programming bug that, when I
figured it out, made me gasp, and then laugh.

In one of my programs I wrote...

c = max(a,b)

...and I was getting the most annoying, frustrating error message:
"type 'int' is not callable."

What the heck? I wasn't calling an integer, I was calling the
__builtin__ function, max()!

I dropped out of my regular editor (SciTE), opened IDLE, and tried
typing in bits of my code, including the call to max(). Everything
seemed to work fine.

Then, I finally spotted the problem. At the beginning of my program I
had defined a variable called "max"! I had overridden the __builtin__
function by mistake.

Is there ever a good reason to override something in __builtin__?
It's powerful, but potentially quite confusing. Can the interpreter
be instructed to give a warning message when you do it?

I believe that that's in the plan somewhere. The difficulty is that
it would undoubtedly break a lot of existing code, so it isn't going
to show up in 2.4 in its full glory. A warning might be feasible,
though.

There's a program (pychecker? I think that's the name) that should
be able to tell you whether you accidentally shadowed a built-in.
Yes indeed, *everything* in Python is an object. Let the newbie
beware!

John Roth
 
I

Ignas Mikalajunas

Yes indeed, *everything* in Python is an object. Let the newbie

Common Lisp solves this problem in a pretty simple way - functions
and variables are in separate namespaces (of course scheme programmers
don't like this very much IIRC) and all global variables are commonly
named *booo* *bah* and etc. so if you are overriding a global variable
you are at least aware of it ...
Ignas Mikalajunas
 
J

Jacek Generowicz

In one of my programs I wrote...

c = max(a,b)
Then, I finally spotted the problem. At the beginning of my program I
had defined a variable called "max"! I had overridden the __builtin__
function by mistake.


Common Lisp solves this problem in a pretty simple way - functions
and variables are in separate namespaces

But it doesn't really _solve_ the problem, does it? It solves the
problem of overriding function bindings with data bindings (and vice
versa), but does nothing to prevent overriding function bindings with
other function bindings. Consider:

def list():
print "list"

and the Common Lisp equivalent

(defun list ()
(print "list"))

In both cases you're clobbering a built-in. The difference, however, is
that, in Python you've merely shadowed the built-in -- the original is
still there in Python's outermost scope (builtins), while in CL you
are attempting to replace the built-in[*].

Common Lisp "solves" it, by forbidding it. But I do not think that
implementations are required to enforce the rule, so some (eg clisp)
complain:

[1]> (defun list () (print "list"))

** - Continuable Error
DEFUN/DEFMACRO(LIST): #<PACKAGE COMMON-LISP> is locked
If you continue (by typing 'continue'): Ignore the lock and proceed
1. Break [2]>

while others (eg CMUCL), let it pass silently:

Loaded subsystems:
Python 1.1, target Intel x86
CLOS 18e (based on PCL September 16 92 PCL (f))
* (defun list () (print "list"))

LIST

(Python, BTW, is the name of CMUCL's compiler :)
all global variables are commonly named *booo* *bah* and etc. so if
you are overriding a global variable you are at least aware of it ...

Although the real purpose of the asterisks is to warn you about the
fact that the variable is dynamically bound[+], and that any local
bindings that you may make for it, will also be dynamic. The asterisks
are another form of namespace separation, but they address an
orthogonal issue, and offer absolutely no protection against
clobbering global _function_ definitions; global function names have
no asterisks (because they are not dynamically bound[#]).


[*] To be fair, Lisp distinguishes global function definitions from
local ones, while in Python they are always local, so one can
argue that the CL equivalent of Python's def is really flet or
labels, which leave the built-in functions well alone, just as is
the case in Python.

[+] As opposed to lexically bound, which is the default in CL, and the
only possibility in Python.

[#] Though it has been suggested recently, that dynamic function
binding subsumes AOP ... but that's getting waaaaay off-topic.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,434
Messages
2,571,690
Members
48,796
Latest member
Greg L.

Latest Threads

Top