<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><br><div><div>On Aug 23, 2010, at 1:03 PM, Guido van Rossum wrote:</div><br><blockquote type="cite"><div><blockquote type="cite">But hasattr() has a far different set of use cases, so we should explore<br></blockquote><blockquote type="cite">an alternate solution to the problem. The usual reason that people use<br></blockquote><blockquote type="cite">hasattr() instead of getattr() is that they want to check for the presence of<br></blockquote><blockquote type="cite">of a method/attribute without actually running it, binding it, or triggering<br></blockquote><blockquote type="cite">any other behavior.<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">As your example shows, property() defeats this intent by actually executing<br></blockquote><blockquote type="cite">the code. A better behavior would not run the code at all. It would check<br></blockquote><blockquote type="cite">the dictionaries along the MRO but not execute any descriptors associated<br></blockquote><blockquote type="cite">with a given key.<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">IMO, this is a much better solution, more in line with known use cases<br></blockquote><blockquote type="cite">for hasattr(). If the proposed change when through, it would fail to<br></blockquote><blockquote type="cite">address the common use case and cause people to start writing their<br></blockquote><blockquote type="cite">own versions of hasattr() that just scan but do not run code.<br></blockquote><br>Hm... That sounds like scope creep to me. Properties are supposed to<br>be cheap and idempotent. Trying to figure out whether an attribute<br>exists without using __getattr__ is fraught with problems -- as soon<br>as a class overrides __getattr__ or __getattribute__ you're hosed<br>anyway.<br></div></blockquote><div><br></div><div>I don't have a specific proposal in mind. My main questions are</div><div><br></div><div>* Is there anything that hasattr(obj, key) can or should do that</div><div> can't already be done with getattr(obj, key, None)? </div><div> If not, do we really need to change anything?</div><div><br></div><div>* Why do people typically use hasattr() instead getattr()? </div><div> Aren't they are really trying to just determine </div><div> whether a key exists somewhere in the MRO?</div><div> If so, then doing anything more than that is probably a surprise.</div><div><br></div><div>I know my own uses of hasattr() do not expect any exceptions at all.</div><div>It comes up in duck typing support different handling for different </div><div>types of inputs. If others are using it the same way, I think it is</div><div>unlikely that they have unittests to cover the possibility that</div><div>hasattr() would ever start raising exceptions.</div><div><br></div><div><br></div><blockquote type="cite"><div>I can vouch that the reason hasattr() catches too many exceptions is<br>that when I first added it (around 1990, I think :-) I wasn't very<br>attuned yet to the problems it could cause.<br></div></blockquote><div><br></div><div>Fire-up the time machine?</div><div><br></div><div><br></div><div>Raymond</div><div><br></div></div><div><br></div><div>P.S. The current behavior seems to be deeply embedded:</div><div><br></div><div><meta charset="utf-8"><span class="Apple-style-span" style="font-family: sans-serif; font-size: 16px; "><dl class="cfunction" style="margin-bottom: 15px; "><dt id="PyObject_HasAttr">int <tt class="descname" style="background-color: transparent; padding-top: 0px; padding-right: 1px; padding-bottom: 0px; padding-left: 1px; font-size: 1.2em; font-weight: bold; ">PyObject_HasAttr</tt><big>(</big><a title="PyObject" class="reference external" href="structures.html#PyObject" style="color: rgb(53, 95, 124); text-decoration: none; ">PyObject</a><em> *o</em>, <a title="PyObject" class="reference external" href="structures.html#PyObject" style="color: rgb(53, 95, 124); text-decoration: none; ">PyObject</a><em> *attr_name</em><big>)</big><a class="headerlink" href="#PyObject_HasAttr" title="Permalink to this definition" style="color: rgb(198, 15, 15); text-decoration: none; visibility: hidden; font-size: 0.8em; padding-top: 0px; padding-right: 4px; padding-bottom: 0px; padding-left: 4px; "></a></dt><dd style="margin-top: 3px; margin-bottom: 10px; margin-left: 30px; text-align: justify; line-height: 20px; ">Returns <tt class="docutils literal" style="background-color: rgb(236, 240, 243); padding-top: 0px; padding-right: 1px; padding-bottom: 0px; padding-left: 1px; font-size: 0.95em; "><span class="pre">1</span></tt> if <em>o</em> has the attribute <em>attr_name</em>, and <tt class="docutils literal" style="background-color: rgb(236, 240, 243); padding-top: 0px; padding-right: 1px; padding-bottom: 0px; padding-left: 1px; font-size: 0.95em; "><span class="pre">0</span></tt> otherwise. This is equivalent to the Python expression <tt class="docutils literal" style="background-color: rgb(236, 240, 243); padding-top: 0px; padding-right: 1px; padding-bottom: 0px; padding-left: 1px; font-size: 0.95em; "><span class="pre">hasattr(o,</span> <span class="pre">attr_name)</span></tt>. This function always succeeds.</dd></dl><dl class="cfunction" style="margin-bottom: 15px; "><dt id="PyObject_HasAttrString">int <tt class="descname" style="background-color: transparent; padding-top: 0px; padding-right: 1px; padding-bottom: 0px; padding-left: 1px; font-size: 1.2em; font-weight: bold; ">PyObject_HasAttrString</tt><big>(</big><a title="PyObject" class="reference external" href="structures.html#PyObject" style="color: rgb(53, 95, 124); text-decoration: none; ">PyObject</a><em> *o</em>, const char<em> *attr_name</em><big>)</big><a class="headerlink" href="#PyObject_HasAttrString" title="Permalink to this definition" style="color: rgb(198, 15, 15); text-decoration: none; visibility: hidden; font-size: 0.8em; padding-top: 0px; padding-right: 4px; padding-bottom: 0px; padding-left: 4px; "></a></dt><dd style="margin-top: 3px; margin-bottom: 10px; margin-left: 30px; text-align: justify; line-height: 20px; ">Returns <tt class="docutils literal" style="background-color: rgb(236, 240, 243); padding-top: 0px; padding-right: 1px; padding-bottom: 0px; padding-left: 1px; font-size: 0.95em; "><span class="pre">1</span></tt> if <em>o</em> has the attribute <em>attr_name</em>, and <tt class="docutils literal" style="background-color: rgb(236, 240, 243); padding-top: 0px; padding-right: 1px; padding-bottom: 0px; padding-left: 1px; font-size: 0.95em; "><span class="pre">0</span></tt> otherwise. This is equivalent to the Python expression <tt class="docutils literal" style="background-color: rgb(236, 240, 243); padding-top: 0px; padding-right: 1px; padding-bottom: 0px; padding-left: 1px; font-size: 0.95em; "><span class="pre">hasattr(o,</span> <span class="pre">attr_name)</span></tt>. This function always succeeds.</dd></dl></span><div><br></div></div><br></body></html>