[Python-Dev] PEP 231, __findattr__()

Guido van Rossum guido@python.org
Mon, 04 Dec 2000 18:16:17 -0500


I'm unconvinced by the __findattr__ proposal as it now stands.

- Do you really think that JimF would do away with ExtensionClasses if
  __findattr__ was intruduced?  I kinda doubt it.  See [*footnote].
  It seems that *using* __findattr__ is expensive (even if *not* using
  is cheap :-).

- Why is deletion not supported?  What if you want to enforce a policy
  on deletions too?

- It's ugly to use the same call for get and set.  The examples
  indicate that it's not such a great idea: every example has *two*
  tests whether it's get or set.  To share a policy, the proper thing
  to do is to write a method that either get or set can use.

- I think it would be sufficient to *only* use __findattr__ for
  getattr -- __setattr__ and __delattr__ already have full control.
  The "one routine to implement the policy" argument doesn't really
  hold, I think.

- The PEP says that the "in-findattr" flag is set on the instance.
  We've already determined that this is not thread-safe.  This is not
  just a bug in the implementation -- it's a bug in the specification.
  I also find it ugly.  But if we decide to do this, it can go in the
  thread-state -- if we ever add coroutines, we have to decide on what
  stuff to move from the thread state to the coroutine state anyway.

- It's also easy to conceive situations where recursive __findattr__
  calls on the same instance in the same thread/coroutine are
  perfectly desirable -- e.g. when __findattr__ ends up calling a
  method that uses a lot of internal machinery of the class.  You
  don't want all the machinery to have to be aware of the fact that it
  may be called with __findattr__ on the stack and without it.  So
  perhaps it may be better to only treat the body of __findattr__
  itself special, as Moshe suggested.  What does Jython do here?

- The code examples require a *lot* of effort to understand.  These
  are complicated issues!  (I rewrote the Bean example using
  __getattr__ and __setattr__ and found no need for __findattr__; the
  __getattr__ version is simpler and easier to understand.  I'm still
  studying the other __findattr__ examples.)

- The PEP really isn't that long, except for the code examples.  I
  recommend reading the patch first -- the patch is probably shorter
  than any specification of the feature can be.

--Guido van Rossum (home page: http://www.python.org/~guido/)

[*footnote]

  There's an easy way (that few people seem to know) to cause
  __getattr__ to be called for virtually all attribute accesses: put
  *all* (user-visible) attributes in a sepate dictionary.  If you want
  to prevent access to this dictionary too (for Zope security
  enforcement), make it a global indexed by id() -- a
  destructor(__del__) can take care of deleting entries here.