On Sat, Feb 22, 2014 at 9:17 PM, Antoine Pitrou <solip...@pitrou.net> wrote: > On Sat, 22 Feb 2014 21:09:07 +1100 > Chris Angelico <ros...@gmail.com> wrote: >> On Sat, Feb 22, 2014 at 8:58 PM, Antoine Pitrou <solip...@pitrou.net> wrote: >> > On Sat, 22 Feb 2014 20:29:27 +1100 >> > Chris Angelico <ros...@gmail.com> wrote: >> >> >> >> Which means that, fundamentally, EAFP is the way to do it. So if PEP >> >> 463 expressions had existed from the beginning, hasattr() probably >> >> wouldn't have been written - people would just use an >> >> except-expression instead. >> > >> > Really? hasattr() is much easier to write than the corresponding >> > except-expression. >> >> But would it be sufficiently easier to justify the creation of a >> built-in? > > 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 the bulk of uses of it are immediately before attempting to use the attribute. Many require multiple statements, so they'd be better done as a full try/except: cpython/python-gdb.py:1392: if not hasattr(self._gdbframe, 'select'): print ('Unable to select frame: ' 'this build of gdb does not expose a gdb.Frame.select method') return False self._gdbframe.select() return True becomes 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 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') (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') 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]) which is similar length and doesn't require a built-in. 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 (also ibid:476) Some are a bit of a mixture. Lib/dis.py:40: if hasattr(x, '__func__'): # Method x = x.__func__ if hasattr(x, '__code__'): # Function x = x.__code__ if hasattr(x, '__dict__'): # Class or module ... lots more code ... Could be done as try/except; first part could be done cleanly as an expression. This one's not quite as clean, but if hasattr didn't exist, this could be done either of two ways: Lib/fileinput.py:342: if hasattr(os, 'O_BINARY'): mode |= os.O_BINARY As an expression: mode |= (os.O_BINARY except AttributeError: 0) Or as a statement: try: mode |= os.O_BINARY except AttributeError: pass This one definitely would want to be changed, and is also going in the PEP: Lib/inspect.py:1350: return sys._getframe(1) if hasattr(sys, "_getframe") else None becomes return (sys._getframe(1) except AttributeError: None) Lib/ntpath.py:558: # Win9x family and earlier have no Unicode filename support. supports_unicode_filenames = (hasattr(sys, "getwindowsversion") and sys.getwindowsversion()[3] >= 2) becomes supports_unicode_filenames = (sys.getwindowsversion()[3] >= 2 except AttributeError: False) Another ternary-if LBYL that could become an expression-except EAFP: Lib/pdb.py:745: globs = self.curframe.f_globals if hasattr(self, 'curframe') else None becomes globs = (self.curframe.f_globals except AttributeError: None) although that will return None if self.curframe has no f_globals. Another nice easy one: Lib/pickletools.py:2227: if hasattr(data, "tell"): getpos = data.tell else: getpos = lambda: None becomes getpos = (data.tell except AttributeError: lambda: None) I could continue this theme, but behold, as Rose Maybud said, I have said enough. There are definitely cases where a local hasattr function could be useful, but if the code were already written to use try/except or an except-expression, there aren't many that would justify the creation of a builtin. ChrisA _______________________________________________ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com