[Python-Dev] PEP 463: Exception-catching expressions

Antoine Pitrou solipsis at pitrou.net
Sat Feb 22 12:27:17 CET 2014


On Sat, 22 Feb 2014 22:13:58 +1100
Chris Angelico <rosuav at gmail.com> wrote:
> >
> > Well, can you propose the corresponding except-expression?
> 
> It's hard to do hasattr itself without something messy - the best I
> can come up with is this:
> 
> hasattr(x,"y") <-> (x.y or True except AttributeError: False)

But it's not the same. hasattr() returns a boolean, not an arbitrary
value.

>         try:
>             self._gdbframe.select()
>             return True
>         except AttributeError:
>             print ('Unable to select frame: '
>                    'this build of gdb does not expose a
> gdb.Frame.select method')
>             return False

But then you can't distinguish between a missing "select" method
and an AttributeError raised by self._gdbframe.select() itself.

> but others are clearly expressions in disguise:
> 
> Lib/aifc.py:882:
>         if hasattr(f, 'mode'):
>             mode = f.mode
>         else:
>             mode = 'rb'
> becomes
>         mode = (f.mode except AttributeError: 'rb')

Not significantly less wordy. Note you can already write:

   mode = getattr(f, 'mode', 'rb')

which is more concise.

> (In fact, I'm adding that one to the PEP's examples section.)
> 
> Lib/cgi.py:145:
>     if hasattr(fp,'encoding'):
>         encoding = fp.encoding
>     else:
>         encoding = 'latin-1'
> becomes
>     encoding = (fp.encoding except AttributeError: 'latin-1')

Same here:

    encoding = getattr(fp, 'encoding', 'latin-1')

> Some could be done either way. If hasattr didn't exist, then this:
> 
> Lib/argparse.py:597:
>             if hasattr(params[name], '__name__'):
>                 params[name] = params[name].__name__
> 
> could be written instead as:
>             params[name] = (params[name].__name__
>                 except AttributeError: params[name])

This makes a useless assignment if the attribute doesn't exist; it also
spans a single expression over two lines instead of having two simple
statements. It's definitely worse IMO.

> Some are fairly clearly asking to be done as try/except, irrespective
> of this PEP:
> 
> Lib/decimal.py:449:
>     if hasattr(threading.current_thread(), '__decimal_context__'):
>         del threading.current_thread().__decimal_context__
> becomes
>     try: del threading.current_thread().__decimal_context__
>     except AttributeError: pass

May hide a bug if threading.current_thread doesn't exist.

> Lib/inspect.py:1350:
>     return sys._getframe(1) if hasattr(sys, "_getframe") else None
> becomes
>     return (sys._getframe(1) except AttributeError: None)

May hide a bug if sys._getframe(1) itself raises AttributeError.

(etc.)

> I could continue this theme, but behold, as Rose Maybud said, I have
> said enough.

Yeah, none of these examples makes a convincing case that hasattr() is
useless, IMO.

Regards

Antoine.




More information about the Python-Dev mailing list