Nick Coghlan wrote:
Benjamin Peterson wrote:
A while ago, Guido declared that all special method lookups on
new-style classes bypass __getattr__ and __getattribute__. This almost
completely consistent now, and I've been working on patching up a few
incorrect cases. I've know hit __enter__ and __exit__. The compiler
generates LOAD_ATTR instructions for these, so it uses the normal
lookup. The only way I can see to fix this is add a new opcode which
uses _PyObject_LookupSpecial, but I don't think we really care this
much. Opinions?
As Georg pointed out, the expectation was that we would eventually add a
SETUP_WITH opcode that used the special method lookup (and hopefully
speed with statements up to a point where they're competitive with
writing out the associated try statement directly). The current code is
the way it is because there is no "LOAD_SPECIAL" opcode and adding type
dereferencing logic to the expansion would have been difficult without a
custom opcode.
For other special methods that are looked up from Python code, the
closest we can ever get is to bypass the instance (i.e. using
"type(obj).__method__(obj, *args)") to avoid metaclass confusion. The
type slots are even *more* special than that because they bypass
__getattribute__ and __getattr__ even on the metaclass for speed reasons.
There's a reason the docs already say that for a guaranteed override you
*must* actually define the special method on the class rather than
merely making it accessible via __getattr__ or even __getattribute__.
The PyPy guys are right to think that some developer somewhere is going
to rely on these implementation details in CPython at some point.
However lots of developers rely on CPython ref counting as well, no
matter how many times they're told not to do that if they want to
support alternative interpreters.
It's actually very annoying for things like writing Mock or proxy
objects when this behaviour is inconsistent (sorry should have spoken up
earlier).
The Python interpreter bases some of its decisions on whether these
methods exist at all - and when you have objects that provide methods
through __getattr__ then you can accidentally get screwed if magic
method lookup returns an object unexpectedly when it should have raised
an AttributeError.
Of course for proxy objects it might be more convenient if *all*
attribute access did go through __getattr__ - but with that not the case
it is much better for it to be consistent rather than have to put in
specific workaround code.
All the best,
Michael
Cheers,
Nick.
--
http://www.ironpythoninaction.com/
http://www.voidspace.org.uk/blog
_______________________________________________
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