[Python-checkins] CVS: python/nondist/peps pep-0252.txt,1.17,1.18

Guido van Rossum gvanrossum@users.sourceforge.net
Sat, 08 Sep 2001 05:42:50 -0700


Update of /cvsroot/python/python/nondist/peps
In directory usw-pr-cvs1:/tmp/cvs-serv868

Modified Files:
	pep-0252.txt 
Log Message:
Quick merge of Barry's feedback of four weeks ago. ;-(


Index: pep-0252.txt
===================================================================
RCS file: /cvsroot/python/python/nondist/peps/pep-0252.txt,v
retrieving revision 1.17
retrieving revision 1.18
diff -C2 -d -r1.17 -r1.18
*** pep-0252.txt	2001/08/07 15:44:15	1.17
--- pep-0252.txt	2001/09/08 12:42:48	1.18
***************
*** 94,98 ****
      attributes).
  
!     Some caution must be exercised: some objects don't list theire
      "intrinsic" attributes (like __dict__ and __doc__) in __members__,
      while others do; sometimes attribute names occur both in
--- 94,98 ----
      attributes).
  
!     Some caution must be exercised: some objects don't list their
      "intrinsic" attributes (like __dict__ and __doc__) in __members__,
      while others do; sometimes attribute names occur both in
***************
*** 137,141 ****
      "static" attributes may actually behave quite dynamically, and
      because they have nothing to do with static class members in C++
!     or Java.)
  
      Examples of dynamic attributes are instance variables of class
--- 137,144 ----
      "static" attributes may actually behave quite dynamically, and
      because they have nothing to do with static class members in C++
!     or Java.  Barry suggests to use immutable and mutable instead, but
!     those words already have precise and different meanings in
!     slightly different contexts, so I think that would still be
!     confusing.)
  
      Examples of dynamic attributes are instance variables of class
***************
*** 207,211 ****
         special case of an attribute descriptor.
  
!        Becase a meta-object is also a regular object, the items in a
         meta-object's __dict__ correspond to attributes of the
         meta-object; however, some transformation may be applied, and
--- 210,214 ----
         special case of an attribute descriptor.
  
!        Because a meta-object is also a regular object, the items in a
         meta-object's __dict__ correspond to attributes of the
         meta-object; however, some transformation may be applied, and
***************
*** 224,232 ****
         relationship between meta-objects defined by __bases__
         attributes; in other words, the __bases__ attributes define an
!        directed acyclic graph.  (It is not necessarily a tree, since
!        multiple classes can have the same base class.)  The __dict__
!        attributes of the meta-objects in the inheritance graph supply
!        attribute descriptors for the regular object whose __class__ is
!        at the top of the inheritance graph.
  
      5. Precedence rules
--- 227,242 ----
         relationship between meta-objects defined by __bases__
         attributes; in other words, the __bases__ attributes define an
!        directed acyclic graph, with arcs pointing from derived
!        meta-objects to their base meta-objects.  (It is not
!        necessarily a tree, since multiple classes can have the same
!        base class.)  The __dict__ attributes of a meta-object in the
!        inheritance graph supply attribute descriptors for the regular
!        object whose __class__ attribute points to the root of the
!        inheritance tree (which is not the same as the root of the
!        inheritance hierarchy -- rather more the opposite, at the
!        bottom given how inheritance trees are typically drawn).
!        Descriptors are first searched in the dictionary of the root
!        meta-object, then in its bases, according to a precedence rule
!        (see the next paragraph).
  
      5. Precedence rules
***************
*** 234,241 ****
         When two meta-objects in the inheritance graph for a given
         regular object both define an attribute descriptor with the
!        same name, the left-to-right depth-first rule applies.  (This
!        is the classic Python attribute lookup rule.  Note that PEP 253
!        will propose to change the attribute lookup order, and if
!        accepted, this PEP will follow suit.)
  
         When a dynamic attribute (one defined in a regular object's
--- 244,253 ----
         When two meta-objects in the inheritance graph for a given
         regular object both define an attribute descriptor with the
!        same name, the search order is up to the meta-object.  This
!        allows different meta-objects to define different search
!        orders.  In particular, classic classes use the old
!        left-to-right depth-first rule, while new-style classes use a
!        more advanced rule (see the section on method resolution order
!        in PEP 253).
  
         When a dynamic attribute (one defined in a regular object's
***************
*** 245,249 ****
         is a descriptor that defines a __set__ method (see below);
         otherwise (if there is no __set__ method) the dynamic attribute
!        has precedence.
  
         Rationale: we can't have a simple rule like "static overrides
--- 257,264 ----
         is a descriptor that defines a __set__ method (see below);
         otherwise (if there is no __set__ method) the dynamic attribute
!        has precedence.  In other words, for data attributes (those
!        with a __set__ method), the static definition overrides the
!        dynamic definition, but for other attributes, dynamic overrides
!        static.
  
         Rationale: we can't have a simple rule like "static overrides
***************
*** 326,350 ****
  
      - __get__(): a function callable with one or two arguments that
!       retrieves the attribute value from an object.  With one
!       argument, X, this either (for data attributes) retrieves the
!       attribute value from X or (for method attributes) binds the
!       attribute to X (returning some form of "bound" object that
!       receives an implied first argument of X when called).  With two
!       arguments, X and T, T must be a meta-object that restricts the
!       type of X.  X must either be an instance of T (in which the
!       effect is the same as when T is omitted), or None.  When X is
!       None, this should be a method descriptor, and the result is an
!       *unbound* method restricted to objects whose type is (a
!       descendent of) T.  Such an unbound method is a descriptor
!       itself.  For methods, this is called a "binding" operation, even
!       if X==None.  Exactly what is returned by the binding operation
!       depends on the semantics of the descriptor; for example, static
!       methods and class methods (see below) ignore the instance and
!       bind to the type instead.
  
      - __set__(): a function of two arguments that sets the attribute
        value on the object.  If the attribute is read-only, this method
!       raises a TypeError exception.  (Not an AttributeError!)
!       Example: C.ivar.set(x, y) ~~ x.ivar = y.
  
  
--- 341,363 ----
  
      - __get__(): a function callable with one or two arguments that
!       retrieves the attribute value from an object.  This is also
!       referred to as a "binding" operation, because it may return a
!       "bound method" object in the case of method descriptors.  The
!       first argument, X, is the object from which the attribute must
!       be retrieved or to which it must be bound.  When X is None, the
!       optional second argument, T, should be meta-object and the
!       binding operation may return an *unbound* method restricted to
!       instances of T.  When both X and T are specified, X should be an
!       instance of T.  Exactly what is returned by the binding
!       operation depends on the semantics of the descriptor; for
!       example, static methods and class methods (see below) ignore the
!       instance and bind to the type instead.
  
      - __set__(): a function of two arguments that sets the attribute
        value on the object.  If the attribute is read-only, this method
!       may raise a TypeError or AttributeError exception (both are
!       allowed, because both are historically found for undefined or
!       unsettable attributes).  Example:
!       C.ivar.set(x, y) ~~ x.ivar = y.
  
  
***************
*** 378,381 ****
--- 391,399 ----
      'c.foo' and an unbound method object for 'C.foo'.
  
+     (XXX Barry suggests to use "sharedmethod" instead of
+     "staticmethod", because the word statis is being overloaded in so
+     many ways already.  But I'm not sure if shared conveys the right
+     meaning.)
+ 
      Class methods use a similar pattern to declare methods that
      receive an implicit first argument that is the *class* for which
***************
*** 432,439 ****
      as its first argument, not class E.  This is to be expected, since
      the call specifies the class C.  But it stresses the difference
!     between these class methods and methods defined in metaclasses
!     (where an upcall to a metamethod would pass the target class as an
!     explicit first argument).  If you don't understand this, don't
!     worry, you're not alone.
  
  
--- 450,462 ----
      as its first argument, not class E.  This is to be expected, since
      the call specifies the class C.  But it stresses the difference
!     between these class methods and methods defined in metaclasses,
!     where an upcall to a metamethod would pass the target class as an
!     explicit first argument.  (If you don't understand this, don't
!     worry, you're not alone.)  Note that calling cls.foo(y) would be a
!     mistake -- it would cause infinite recursion.  Also note that you
!     can't specify an explicit 'cls' argument to a class method.  If
!     you want this (e.g. the __new__ method in PEP 253 requires this),
!     use a static method with a class as its explicit first argument
!     instead.
  
  
***************
*** 568,574 ****
        nondata descriptors.  The current implementation quite sensibly
        classifies member and getset descriptors as data (even if they
!       are read-only!)  and member descriptors as nondata.
        Non-descriptors (like function pointers or plain values) are
!       also classified as non-data.
  
      - This scheme has one drawback: in what I assume to be the most
--- 591,597 ----
        nondata descriptors.  The current implementation quite sensibly
        classifies member and getset descriptors as data (even if they
!       are read-only!)  and method descriptors as nondata.
        Non-descriptors (like function pointers or plain values) are
!       also classified as non-data (!).
  
      - This scheme has one drawback: in what I assume to be the most
***************
*** 605,609 ****
        ['append', 'count', 'extend', 'index', 'insert', 'pop',
        'remove', 'reverse', 'sort']
!       >>> 
  
      Under the new proposal, the __methods__ attribute no longer exists:
--- 628,632 ----
        ['append', 'count', 'extend', 'index', 'insert', 'pop',
        'remove', 'reverse', 'sort']
!       >>>
  
      Under the new proposal, the __methods__ attribute no longer exists: