Thursday, June 23, 2011

Dict Destroyer!

Let's make a class that returns a random number for its hash.

>>> import random
>>> class DictDestroyer(object):
...    def __hash__(self):  return random.randint(0, 2**31)
...
>>> d = DictDestroyer()
>>> hash(d)
520880499
>>> hash(d)
793941724

Now, DictDestroyer lives up to its name:

>>> a = {d:1, d:2, d:3}
>>> import pprint
>>> pprint.pprint(a)
{<__main__.DictDestroyer object at 0x00CE8E90>: 1,
 <__main__.DictDestroyer object at 0x00CE8E90>: 2,
 <__main__.DictDestroyer object at 0x00CE8E90>: 3}

What is this?  One key has multiple values?  What happens when data is fetched?

>>> a[d]
1
>>> a[d]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: <__main__.DictDestroyer object at 0x00CE8E90>

Inconsistent behavior.  Some times it returns one of the values, other times it gives a key error.
The C source for python dictionaries holds the answer.
I'll have to update later when I figure it out.

Wednesday, June 22, 2011

cron-like functionality (sched module)

The Python standard library includes a handy little scheduler, with which you can do cron-like functionality.  The following code will print the current time every 5 seconds forever.

>>> import sched
>>> import datetime
>>> import time
>>> s = sched.scheduler(time.time, time.sleep)
>>> def print_time():
...    print datetime.datetime.now()
...    s.enter(5, 1, print_time, ())
...
>>> print_time()
2011-06-22 17:56:41.262000
>>> s.run()
2011-06-22 17:56:46.668000
2011-06-22 17:56:51.669000
2011-06-22 17:56:56.669000
2011-06-22 17:57:01.669000

This is a simple example of continuation passing style -- where functions "schedule" each other to run at a later time rather than calling directly.

Sunday, May 29, 2011

inner functions, how do they work?

When a higher order function returns a new function, a new context has been wrapped around the existing code object.  The code of that function is created once, at compile time.  There is absolutely no compiler involved at runtime, no new byte code is generated.

>>> def foo(n):
...    def bar():
...       print n
...    return bar
...
>>> a,b = foo(1), foo(2)
>>> a == b
False
>>> a()
1
>>> b()
2
>>> a.__code__ == b.__code__
True

Wednesday, May 18, 2011

__class__ is special

>>> class Classless(object):
...    def __getattr__(self, name): raise AttributeError(name)
...
>>> Classless().__class__
<class '__main__.Classless'>
>>> c = Classless()
>>> c.__class__ = None
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: __class__ must be set to new-style class, not 'NoneType' object

Monday, May 16, 2011

the keys to the kingdom

Most of the low-level guts of an operating system are only exposed to C.  Enter ctypes, part of the python standard library which allows python to call C code natively.

For example, say you are trying to access some function of open-ssl that is not exposed through the ssl module.

>>> import ctypes
>>> libssl = ctypes.cdll.LoadLibrary('libssl.so')
>>> libssl.PEM_read_bio_PrivateKey
<_FuncPtr object at 0x7fc001ba3a10>

With ctypes, your code is a full peer of C/C++ in how it can interact with the OS.

Thursday, May 5, 2011

reloading a module does not regenerate the module object

When a module is reloaded, the module object is not removed from memory.  Old data which is not overwritten will stick around.

>>> import json
>>> oldjson = json
>>> reload(json)
<module 'json' from 'C:\Python26\lib\json\__init__.pyc'>
>>> json is oldjson
True

To truly clean up modules in memory is a tricky process.

Wednesday, April 20, 2011

making dict(myobject) do something useful

>>> class T(object):
...    def __iter__(self):
...       return self.__dict__.items().__iter__()
...
>>> t = T()
>>> t.a = "cat"; t.b = "dog"
>>> dict(t)
{'a': 'cat', 'b': 'dog'}