foo.bar is compiled to call __getattr__ if invoked in a get context; see CodeCompiler#visitAttribute
Here is a short history of __findattr__, __getattr__ and
__getattribute__, and why PyObject#object___getattribute__ can't
directly call PyObject#__getattr__. I learned this in the hard way,
but that's what you get when you attempt to modify a core component of
the runtime without understanding all this:
What are __findattr__ and __getattr__?
- PyObject#__findattr__: Has the semantics of Python's
__getattribute__ (that is, is called before looking on the object
dict), but returns null instead of throwing Py.AttributeError when the
- PyObject#__getattr__: Same as __findattr__ but *does* throws
AttributeError and never returns null. Currently it is implemented in
terms of __findattr__, in the obvious way. PyObject subclasses are
expected to override __findattr__.
When are they used?
- From Java code wanting to access attributes of PyObjects.
- When you do getattr(foo, bar) on Python code [and I'd bet that when
you do foo.bar too, but I've not looked at the exact locations].
And what about __getattribute__?
- There are methods *exposed* through the __getattribute__ descriptor
which get called when you do foo.__getattribute__(bar) or
But who uses that syntax?
- Typical use is in custom implementations of __getattribute__:
def __getattribute__(self, attr):
if attr == "bar":
- And who knows who other, what's important is that it should work!
So foo.__getattribute__('bar') should always be the same as
getattribute(foo, 'bar') for new-style classes?
- Yes. That's why every new-style PyObject subclass overriding
__findattr__ should also expose __getattribute__. And both should
follow exactly the same logic.
Cool. So what if we avoid all that repetition by making
object___getattribute__ call __getattr__?
- Does *not* work. By doing that object.__getattribute__(x, y) would
call x.object___getattribute__(y) and would end calling
x.__findattr__(y) which would invoke the *overriden* __getattr__
logic, not the *original* object's __getattr__ logic. That's quite bad
for derived types with custom __getattribute__ implementation (such as
the "Foo" class shown above), because this means going into an
What *seems* reasonable now is that each overriden __findattr__()
simply call the exposed __getattribute__ and not the other way around.
If the lookup could be delegated to super, then the __getattribute__
method should invoke super.__findattr__().
Leo Soto M.
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
Jython-dev mailing list