[Python-Dev] New syntax for 'dynamic' attribute access
Nick Coghlan
ncoghlan at gmail.com
Tue Feb 13 14:37:29 CET 2007
Taking a step back a bit... the basic issue is that we have an attribute
namespace (compile time key determination) that we want to access in a
dictionary style (runtime key determination).
This is currently done by switching from syntactic access to the
getattr/setattr/delattr builtin functions.
Elsewhere in the thread, Calvin made the suggestion that, rather than
introducing new syntax, this could instead be achieved with a wrapper
class that automatically converted dict-style access into the
appropriate calls to getattr/setattr/delattr.
I've tried this out on Brett's urllib & urllib2 examples below. (calling
the new builtin attrview() to emphasise the fact that it retains a
reference to the original instance). I don't consider it any uglier than
the proposed syntax changes, and it provides a few other benefits:
- the two-argument form is naturally available as the .get() method
on the resulting dict-like object (e.g. "attrview(obj).get(some_attr,
None)")
- hasattr() is naturally replaced by containment testing (e.g.
"some_attr in attrview(obj)")
- keywords/builtins are easier to look up in the documentation than
symbolic syntax
With this approach, performance would be attained by arranging to create
the view objects once, and then performing multiple dynamic attribute
accesses using those view objects.
First urllib.py example::
name = 'open_' + urltype
self.type = urltype
name = name.replace('-', '_')
self_d = attrview(self)
if name in self_d:
if proxy:
return self.open_unknown_proxy(proxy, fullurl, data)
else:
return self.open_unknown(fullurl, data)
try:
if data is None:
return self_d[name](url)
else:
return self_d[name](url, data)
except socket.error, msg:
raise IOError, ('socket error', msg), sys.exc_info()[2]
Second urllib.py example::
name = 'http_error_%d' % errcode
self_d = attrview(self)
if name in self_d:
method = self_d[name]
if data is None:
result = method(url, fp, errcode, errmsg, headers)
else:
result = method(url, fp, errcode, errmsg, headers, data)
if result: return result
return self.http_error_default(url, fp, errcode, errmsg, headers)
First urllib.py example::
if attr[:12] == '_Request__r_':
name = attr[12:]
get_name = 'get_' + name
if get_name in attrview(Request):
self_d = attrview(self)
self_d[get_name]()
return self_d[attr]
raise AttributeError, attr
Second urllib2.py example::
handlers = chain.get(kind, ())
for handler in handlers:
func = attrview(handler)[meth_name]
result = func(*args)
if result is not None:
return result
Regards,
Nick.
--
Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia
---------------------------------------------------------------
http://www.boredomandlaziness.org
More information about the Python-Dev
mailing list