Pedram Amini has got a pretty neat post up on reverse engineering the protocol for a USB device. If you haven’t seen it yet (it was linked from Slashdot) it’s worth reading. However, he includes some Python code which features a puzzling (to me, anyway) idiom, which took me a while to figure out.
How Does This Work?
Pedram’s code includes the following snippets:
class web_interface_handler (BaseHTTPServer.BaseHTTPRequestHandler):
def __init__(self, request, client_address, server):
BaseHTTPServer.BaseHTTPRequestHandler.__init__(self, request, client_address, server)
self.missile = None
and
class web_interface_server (BaseHTTPServer.HTTPServer):
def __init__(self, server_address, RequestHandlerClass, missile):
BaseHTTPServer.HTTPServer.__init__(self, server_address, RequestHandlerClass)
self.RequestHandlerClass.missile = missile
and
self.server = web_interface_server(('', 12345), web_interface_handler, self.missile)
What’s puzzling is that web_interface_server.__init__()
sets a web_interface_handler
class-level missile
member, while web_interface_handler.__init__()
sets an instance-level missile
member (to None
). Since the instance-level member will take precedence, how can a reference ever be made to the class-level missile
member?
The Trick
The relevant code is in the BaseRequestHandler.__init__()
function:
def __init__(self, request, client_address, server):
self.request = request
self.client_address = client_address
self.server = server
try:
self.setup()
self.handle()
self.finish()
finally:
sys.exc_traceback = None # Help garbage collection
This code is not overridden by the BaseHTTPRequestHandler
class (which inherits from it, and from which web_interface_handler
inherits). The significance of this code is that all the “work” done by a BaseRequestHandler
instance is done when it is initialized. Since this initialization code is invoked by web_interface_server.__init__()
before that function sets the instance-level missile
member, the code can make reference to the class-level member.
I would categorize this as “non-obvious”.