[Python-Dev] PEP-able

Gordon McMillan gmcm@hypernet.com
Thu, 20 Jul 2000 09:43:33 -0400


Paul Prescod wrote:

[Title: Computed Attributes]

> Semantics
 
>     It is disallowed to actually have an attribute named y in the
>     dictionary for reasons that will become clear when we discuss
>     the implementation.

What happens here (and when):
class A:
  y = None
class B(A):
  def __XXX_y__(self):
     ...
 
>     An implementation of __get_y__ takes precedence over an
>     implementation of __getattr__ based on the principle that
>     __getattr__ is supposed to be invoked only after finding an
>     appropriate attribute has failed. This is important for
>     acceptable performance.

Hmmm. Current Python: search for y fails, try __getattr__. 
Proposed: search for y fails, try the __get_y__, then 
__getattr__. We've still done the same work before trying the 
hook, so how is performance affected? Or are you proposing 
to try the hook first, thus improving performance for hooked 
attributes at the price of degrading performance for all non-
hooked attributes?

> Proposed Implementation
> 
>     There is a new object called a computed attribute object. It
>     has three attributes: get, set, delete. In PyClass_New,
>     methods of the appropriate form will be detected and
>     converted into objects (just like unbound method objects). 
>     Matching methods go in the same computed attribute object and
>     missing methods are replaced with a stub that throws the
>     TypeError. If there are any computed attributes at all, a
>     flag is set. Let's call it "I_have_computed_attributes" for
>     now.

class A:
  def __get_y__(self):
    ...
class B(A):
  def __set_y__(self, value):
    ....

Notice a problem here? Is it B's author's intent to make a read-
only attribute read-write (in which case the accessor object 
probably needs to get copied from A.__dict__ to B.__dict__ 
so as not to interfere with other derived classes)? Or do we 
assume he wants to make it write-only, and to make it read-
write does he need to do:
class B(A):
  def __set_y__(self, value):
    ....
  def __get_y__(self):
    return A.__get_y__(self)

(which involves another wrinkle, because there is no attribute 
"__get_y__" in class A).
 


- Gordon