On Tue, Apr 5, 2011 at 05:01, Nick Coghlan <ncogh...@gmail.com> wrote:
> On Tue, Apr 5, 2011 at 9:46 AM, Brett Cannon <br...@python.org> wrote: > > try: > > c_heapq.heappop(Spam()) > > except TypeError: > > # "heap argument must be a list" > > pass > > > > try: > > py_heapq.heappop(Spam()) > > except AttributeError: > > # "'Foo' object has no attribute 'pop'" > > pass > > > > This kind of divergence is a problem for users as they unwittingly > > write code that is CPython-specific. This is also an issue for other > > VM teams as they have to deal with bug reports from users thinking > > that they incorrectly implemented the module when in fact it was > > caused by an untested case. > > While I agree with the PEP in principle, I disagree with the way this > example is written. Guido has stated in the past that code simply > *cannot* rely on TypeError being consistently thrown instead of > AttributeError (or vice-versa) when it comes to duck-typing. Code that > cares which of the two is thrown is wrong. > Which is unfortunate since least common base class is Exception. But I can add a note to the PEP saying that this is the case and change the example. > > However, there actually *is* a significant semantic discrepancy in the > heapq case, which is that py_heapq is duck-typed, while c_heapq is > not: > > >>> from test.support import import_fresh_module > >>> c_heapq = import_fresh_module('heapq', fresh=['_heapq']) > >>> py_heapq = import_fresh_module('heapq', blocked=['_heapq']) > >>> from collections import UserList > >>> class Seq(UserList): pass > ... > >>> c_heapq.heappop(UserList()) > Traceback (most recent call last): > File "<stdin>", line 1, in <module> > TypeError: heap argument must be a list > >>> py_heapq.heappop(UserList()) > Traceback (most recent call last): > File "<stdin>", line 1, in <module> > File "/home/ncoghlan/devel/py3k/Lib/heapq.py", line 140, in heappop > lastelt = heap.pop() # raises appropriate IndexError if heap is empty > File "/home/ncoghlan/devel/py3k/Lib/collections/__init__.py", line 848, in > pop > def pop(self, i=-1): return self.data.pop(i) > IndexError: pop from empty list > > Cheers, > Nick. > > P.S. The reason I was bugging Guido to answer the TypeError vs > AttributeError question in the first place was to find out whether or > not I needed to get rid of the following gross inconsistency in the > behaviour of the with statement relative to other language constructs: > > >>> 1() > Traceback (most recent call last): > File "<stdin>", line 1, in <module> > TypeError: 'int' object is not callable > >>> with 1: pass > ... > Traceback (most recent call last): > File "<stdin>", line 1, in <module> > AttributeError: 'int' object has no attribute '__exit__' > > > > Cheers, > Nick. > > -- > Nick Coghlan | ncogh...@gmail.com | Brisbane, Australia >
_______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com