Evil hack of the day

Neel Krishnaswami neelk at brick.cswv.com
Wed May 26 19:19:05 EDT 1999


Well, I've found a solution to the "how do I imitate a C static
variable" question that's so gratuitously evil that it should never be
used, and should probably be forgotten immediately. Of course, I feel
like sharing. :)

The standard bad solution to the problem is something like this:

def merely_bad(n=[0]):
    n[0] = n[0] + 1
    return n[0]

This exploits default arguments and the mutability of lists to cause
the function to return the number of times it has been called. 

However, I was looking at the attributes of a function object, and
noticed that it had an interesting-looking attribute named
func_defaults.  When I looked at it it, I saw that it seemed to be a
tuple containing the functions default arguments. "Hmm," I wondered,
"I wonder if I could assign to it." And lo and behold I could!

This leads to the evil version:

>>> def evil(n=0):
... 	n = n + 1
... 	globals()['evil'].func_defaults = (n,)
... 	return n
...
>>> evil()
1
>>> evil()
2
>>> evil()
3

This approach misuses the default argument syntax, relies on an
implementation detail, *and* gratuitously exploits Python's
dynamism. The only way I can see to top it is to mess around with the
func_code attribute. (Now I just need to download bytecodehacks....)


Neel




More information about the Python-list mailing list