[Python-Dev] New syntax for 'dynamic' attribute access (original) (raw)
Brett Cannon brett at python.org
Tue Feb 13 21:05:43 CET 2007
- Previous message: [Python-Dev] New syntax for 'dynamic' attribute access
- Next message: [Python-Dev] New syntax for 'dynamic' attribute access
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
On 2/13/07, Nick Coghlan <ncoghlan at gmail.com> wrote:
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.
In other words, an object view analagous to what Py3K is doing with keys()/values()/items().
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(someattr, None)") - hasattr() is naturally replaced by containment testing (e.g. "someattr in attrview(obj)") - keywords/builtins are easier to look up in the documentation than symbolic syntax
Yeah, the generalization is really nice. It allows use to ditch getattr/setattr/hasattr all without losing the expressiveness of those built-ins.
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('-', '') selfd = attrview(self) if name in selfd: if proxy: return self.openunknownproxy(proxy, fullurl, data) else: return self.openunknown(fullurl, data) try: if data is None: return selfdname else: return selfd[name](url, data) except socket.error, msg: raise IOError, ('socket error', msg), sys.excinfo()[2] Second urllib.py example:: name = 'httperror%d' % errcode selfd = attrview(self) if name in selfd: method = selfd[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.httperrordefault(url, fp, errcode, errmsg, headers)
First urllib.py example:: if attr[:12] == 'Request_r': name = attr[12:] getname = 'get' + name if getname in attrview(Request): selfd = attrview(self) selfdgetname return selfd[attr] raise AttributeError, attr Second urllib2.py example:: handlers = chain.get(kind, ()) for handler in handlers: func = attrview(handler)[methname] result = func(*args) if result is not None: return result
I also think it is just as clean as doing it any of the proposed ways::
getattr(self, name) self.[name] attrview(self)[name]
So my vote is for Nick's object attribute view; +1. If we are going to do the view thing, let's go all the way! =)
-Brett
- Previous message: [Python-Dev] New syntax for 'dynamic' attribute access
- Next message: [Python-Dev] New syntax for 'dynamic' attribute access
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]