<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Wed, Sep 13, 2017 at 2:00 PM, Nathaniel Smith <span dir="ltr"><<a href="mailto:njs@pobox.com" target="_blank">njs@pobox.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">On Wed, Sep 13, 2017 at 11:49 AM, Guido van Rossum <<a href="mailto:guido@python.org">guido@python.org</a>> wrote:<br>
>  > Why not adding both? Properties do have their uses as does __getattr__.<br>
><br>
> In that case I would just add __getattr__ to module.c, and add a recipe or<br>
> perhaps a utility module that implements a __getattr__ you can put into your<br>
> module if you want @property support. That way you can have both but you<br>
> only need a little bit of code in module.c to check for __getattr__ and call<br>
> it when you'd otherwise raise AttributeError.<br>
<br>
</span>Unfortunately I don't think this works. If there's a @property object<br>
present in the module's instance dict, then __getattribute__ will<br>
return it directly instead of calling __getattr__.<br></blockquote><div><br></div><div>Hm, that's a good point. One would have to introduce some kind of convention where you can write properties with a leading _:<br></div><div><br></div><div>@property</div><div>def _foo(): return 42</div><div><br></div><div>and then a utility __getattr__ like this:</div><div><br></div><div>def __getattr__(name):</div><div>    g = globals()</div><div>    name = '_' + name</div><div>    if name in g:</div><div>        return g[name]()</div><div>    raise AttributeError(...)<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
(I guess for full property emulation you'd also need to override<br>
__setattr__ and __dir__, but I don't know how important that is.)<br></blockquote><div><br></div><div>At that point maybe __class__ assignment is better.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
We could consider letting modules overload __getattribute__ instead of<br>
__getattr__, but I don't think this is viable either -- a key feature<br>
of __getattr__ is that it doesn't add overhead to normal lookups. If<br>
you implement deprecation warnings by overloading __getattribute__,<br>
then it makes all your users slower, even the ones who never touch the<br>
deprecated attributes. __getattr__ is much better than<br>
__getattribute__ for this purpose.<br></blockquote><div><br></div><div>Agreed.</div><div> <br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Alternatively we can have a recipe that implements @property support<br>
using __class__ assignment and overriding<br>
__getattribute__/__setattr__/_<wbr>_dir__, so instead of 'from<br>
module_helper.property_<wbr>emulation import __getattr__' it'd be 'from<br>
module_helper import enable_property_emulation;<br>
enable_property_emulation(__<wbr>name__)'. Still has the slowdown problem<br>
but it would work.<br></blockquote></div></div><div class="gmail_extra"><br></div><div class="gmail_extra">The emulation could do something less drastic than __class__ assignment -- it could look for globals that are properties, move them into some other dict (e.g. __properties__), and install a __getattr__ that looks things up in that dict and calls them.</div><div class="gmail_extra"><br></div><div class="gmail_extra">def __getattr__(name):</div><div class="gmail_extra">    if name in __properties__:<br></div><div class="gmail_extra">        return __properties__[name]()<br clear="all"></div><div class="gmail_extra">    raise AttributeError(...)</div><div class="gmail_extra"><br></div><div class="gmail_extra">Still, proposals for sys.py notwithstanding, I'm worried that all of this is a solution looking for a problem. Yes, it's a cute hack. But is it art?<br></div><div class="gmail_extra"><br></div><div class="gmail_extra">-- <br><div class="gmail_signature" data-smartmail="gmail_signature">--Guido van Rossum (<a href="http://python.org/~guido" target="_blank">python.org/~guido</a>)</div>
</div></div>