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

Tim Peters tim_one@users.sourceforge.net
Fri, 21 Sep 2001 00:56:19 -0700


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

Modified Files:
	pep-0253.txt 
Log Message:
Fixed a number of typos, and made some semantic updates in a few areas I
was sure about.


Index: pep-0253.txt
===================================================================
RCS file: /cvsroot/python/python/nondist/peps/pep-0253.txt,v
retrieving revision 1.16
retrieving revision 1.17
diff -C2 -d -r1.16 -r1.17
*** pep-0253.txt	2001/09/08 11:31:52	1.16
--- pep-0253.txt	2001/09/21 07:56:16	1.17
***************
*** 108,112 ****
      >>> type(type(type(a)))
      <type 'type'>
!     >>> 
  
      In this example, type(a) is a "regular" type, and type(type(a)) is
--- 108,112 ----
      >>> type(type(type(a)))
      <type 'type'>
!     >>>
  
      In this example, type(a) is a "regular" type, and type(type(a)) is
***************
*** 147,151 ****
      and initialize it at will.)
  
!     Metatypes determine various *policies* for types,such as what
      happens when a type is called, how dynamic types are (whether a
      type's __dict__ can be modified after it is created), what the
--- 147,151 ----
      and initialize it at will.)
  
!     Metatypes determine various *policies* for types, such as what
      happens when a type is called, how dynamic types are (whether a
      type's __dict__ can be modified after it is created), what the
***************
*** 224,234 ****
      should always be a new reference, owned by the caller.
  
!     One the tp_new slot has returned an object, further initialization
      is attempted by calling the tp_init() slot of the resulting
      object's type, if not NULL.  This has the following signature:
  
!         PyObject *tp_init(PyObject *self,
!                           PyObject *args,
!                           PyObject *kwds)
  
      It corresponds more closely to the __init__() method of classic
--- 224,234 ----
      should always be a new reference, owned by the caller.
  
!     Once the tp_new slot has returned an object, further initialization
      is attempted by calling the tp_init() slot of the resulting
      object's type, if not NULL.  This has the following signature:
  
!          int tp_init(PyObject *self,
!                      PyObject *args,
!                      PyObject *kwds)
  
      It corresponds more closely to the __init__() method of classic
***************
*** 238,242 ****
      they ensure.  The tp_new() slot should ensure only the most
      essential invariants, without which the C code that implements the
!     object's would break.  The tp_init() slot should be used for
      overridable user-specific initializations.  Take for example the
      dictionary type.  The implementation has an internal pointer to a
--- 238,242 ----
      they ensure.  The tp_new() slot should ensure only the most
      essential invariants, without which the C code that implements the
!     objects would break.  The tp_init() slot should be used for
      overridable user-specific initializations.  Take for example the
      dictionary type.  The implementation has an internal pointer to a
***************
*** 273,276 ****
--- 273,280 ----
      (or raise an exception).
  
+     Both tp_new() and tp_init() should receive exactly the same 'args'
+     and 'kwds' arguments, and both should check that the arguments are
+     acceptable, because they may be called independently.
+ 
      There's a third slot related to object creation: tp_alloc().  Its
      responsibility is to allocate the memory for the object,
***************
*** 292,296 ****
          type->tp_basicsize  +  nitems * type->tp_itemsize
  
!     This slot is only used for subclassable types.  The tp_new()
      function of the base class must call the tp_alloc() slot of the
      type passed in as its first argument.  It is the tp_new()
--- 296,300 ----
          type->tp_basicsize  +  nitems * type->tp_itemsize
  
!     The tp_alloc slot is only used for subclassable types.  The tp_new()
      function of the base class must call the tp_alloc() slot of the
      type passed in as its first argument.  It is the tp_new()
***************
*** 304,314 ****
      are renamed to tp_allocs and tp_deallocs.)
  
-     XXX The keyword arguments are currently not passed to tp_new();
-     its kwds argument is always NULL.  This is a relic from a previous
-     revision and should probably be fixed.  Both tp_new() and
-     tp_init() should receive exactly the same arguments, and both
-     should check that the arguments are acceptable, because they may
-     be called independently.
- 
      Standard implementations for tp_alloc() and tp_new() are
      available.  PyType_GenericAlloc() allocates an object from the
--- 308,311 ----
***************
*** 333,337 ****
      of the base structure unchanged) and can override certain slots in
      the type object, leaving others the same.  (Unlike C++ vtables,
!     all Python type objects have the same memory lay-out.)
  
      The base type must do the following:
--- 330,334 ----
      of the base structure unchanged) and can override certain slots in
      the type object, leaving others the same.  (Unlike C++ vtables,
!     all Python type objects have the same memory layout.)
  
      The base type must do the following:
***************
*** 358,362 ****
      at the end of an object's lifetime.  The slots involved are
      tp_dealloc() (familiar to all who have ever implemented a Python
!     extension type) and tp_free(), the new kid on he block.  (The
      names aren't quite symmetric; tp_free() corresponds to tp_alloc(),
      which is fine, but tp_dealloc() corresponds to tp_new().  Maybe
--- 355,359 ----
      at the end of an object's lifetime.  The slots involved are
      tp_dealloc() (familiar to all who have ever implemented a Python
!     extension type) and tp_free(), the new kid on the block.  (The
      names aren't quite symmetric; tp_free() corresponds to tp_alloc(),
      which is fine, but tp_dealloc() corresponds to tp_new().  Maybe
***************
*** 399,403 ****
      with instances of the derived type.  Before enabling subtyping of
      a particular type, its code should be checked to make sure that
!     this won't break anything.
  
  
--- 396,405 ----
      with instances of the derived type.  Before enabling subtyping of
      a particular type, its code should be checked to make sure that
!     this won't break anything.  It has proved useful in the prototype
!     to add another type-checking macro for the built-in Python object
!     types, to check for exact type match too (for example,
!     PyDict_Check(x) is true if x is an instance of dictionary or of a
!     dictionary subclass, while PyDict_CheckExact(x) is true only if x
!     is a dictionary).
  
  
***************
*** 428,432 ****
      additions.  Also note that the base type is not referenced via a
      pointer; the actual contents of its structure must be included!
!     (The goal is for the memory lay out of the beginning of the
      subtype instance to be the same as that of the base type
      instance.)
--- 430,434 ----
      additions.  Also note that the base type is not referenced via a
      pointer; the actual contents of its structure must be included!
!     (The goal is for the memory layout of the beginning of the
      subtype instance to be the same as that of the base type
      instance.)
***************
*** 554,559 ****
          C = M("C", (B,), dict)
  
!     (where dict is the dictionary resulting from execution of the
!     class body).  In other words, the metatype (M) is called.
  
      Note that even though the example has only one base, we still pass
--- 556,561 ----
          C = M("C", (B,), dict)
  
!     where dict is the dictionary resulting from execution of the
!     class body.  In other words, the metatype (M) is called.
  
      Note that even though the example has only one base, we still pass
***************
*** 578,586 ****
      There are two further refinements here.  First, a useful feature
      is to be able to specify a metatype directly.  If the class
!     statement defines a variable __metaclass__, that is the metatype
      to call.  (Note that setting __metaclass__ at the module level
      only affects class statements without a base class and without an
      explicit __metaclass__ declaration; but setting __metaclass__ in a
!     class statement overrides the default metatype unconditionally.)
  
      Second, with multiple bases, not all bases need to have the same
--- 580,588 ----
      There are two further refinements here.  First, a useful feature
      is to be able to specify a metatype directly.  If the class
!     suite defines a variable __metaclass__, that is the metatype
      to call.  (Note that setting __metaclass__ at the module level
      only affects class statements without a base class and without an
      explicit __metaclass__ declaration; but setting __metaclass__ in a
!     class suite overrides the default metatype unconditionally.)
  
      Second, with multiple bases, not all bases need to have the same
***************
*** 591,596 ****
      raised and the class statement fails.
  
!     This conflict resultion can be implemented in the metatypes
!     itself: the class statement just calls the metatype of the first
      base (or that specified by the __metaclass__ variable), and this
      metatype's constructor looks for the most derived metatype.  If
--- 593,598 ----
      raised and the class statement fails.
  
!     This conflict resolution can be implemented by the metatype
!     constructors: the class statement just calls the metatype of the first
      base (or that specified by the __metaclass__ variable), and this
      metatype's constructor looks for the most derived metatype.  If
***************
*** 622,636 ****
  
      In any case, the work for creating C is done by M's tp_new() slot.
!     It allocates space for an "extended" type structure, which
!     contains space for: the type object; the auxiliary structures
!     (as_sequence etc.); the string object containing the type name (to
!     ensure that this object isn't deallocated while the type object is
!     still referencing it); and some more auxiliary storage (to be
!     described later).  It initializes this storage to zeros except for
!     a few crucial slots (for example, tp_name is set to point to the
!     type name) and then sets the tp_base slot to point to B.  Then
!     PyType_InitDict() is called to inherit B's slots.  Finally, C's
!     tp_dict slot is updated with the contents of the namespace
!     dictionary (the third argument to the call to M).
  
  
--- 624,637 ----
  
      In any case, the work for creating C is done by M's tp_new() slot.
!     It allocates space for an "extended" type structure, containing:
!     the type object; the auxiliary structures (as_sequence etc.); the
!     string object containing the type name (to ensure that this object
!     isn't deallocated while the type object is still referencing it); and
!     some auxiliary storage (to be described later).  It initializes this
!     storage to zeros except for a few crucial slots (for example, tp_name
!     is set to point to the type name) and then sets the tp_base slot to
!     point to B.  Then PyType_InitDict() is called to inherit B's slots.
!     Finally, C's tp_dict slot is updated with the contents of the
!     namespace dictionary (the third argument to the call to M).
  
  
***************
*** 673,679 ****
      (Here, 'dictionary' is the type of built-in dictionary objects,
      a.k.a. type({}) or {}.__class__ or types.DictType.)  If we look at
!     the structure lay-out, we find that an A instance has the lay-out
      of a dictionary followed by the __dict__ pointer, and a B instance
!     has the same lay-out; since there are no structure member lay-out
      conflicts, this is okay.
  
--- 674,680 ----
      (Here, 'dictionary' is the type of built-in dictionary objects,
      a.k.a. type({}) or {}.__class__ or types.DictType.)  If we look at
!     the structure layout, we find that an A instance has the layout
      of a dictionary followed by the __dict__ pointer, and a B instance
!     has the same layout; since there are no structure member layout
      conflicts, this is okay.
  
***************
*** 689,693 ****
  
      (Here, 'object' is the base for all built-in types; its structure
!     lay-out only contains the ob_refcnt and ob_type members.)  This
      example is more complicated, because the __dict__ pointer for X
      instances has a different offset than that for Y instances.  Where
--- 690,694 ----
  
      (Here, 'object' is the base for all built-in types; its structure
!     layout only contains the ob_refcnt and ob_type members.)  This
      example is more complicated, because the __dict__ pointer for X
      instances has a different offset than that for Y instances.  Where
***************
*** 701,705 ****
      followed by a __dict__ pointer), and a Y structure is 64 bytes (a
      dictionary structure followed by a __dict__ pointer).  The Z
!     structure has the same lay-out as the Y structure in this example.
      Each type object (X, Y and Z) has a "__dict__ offset" which is
      used to find the __dict__ pointer.  Thus, the recipe for looking
--- 702,706 ----
      followed by a __dict__ pointer), and a Y structure is 64 bytes (a
      dictionary structure followed by a __dict__ pointer).  The Z
!     structure has the same layout as the Y structure in this example.
      Each type object (X, Y and Z) has a "__dict__ offset" which is
      used to find the __dict__ pointer.  Thus, the recipe for looking
***************
*** 723,727 ****
  
  
! Method resolution order (the lookup rule)
  
      With multiple inheritance comes the question of method resolution
--- 724,728 ----
  
  
! MRO:  Method resolution order (the lookup rule)
  
      With multiple inheritance comes the question of method resolution
***************
*** 777,781 ****
      hierarchies use single inheritance, and multiple inheritance is
      usually confined to mix-in classes.  In fact, the problem shown
!     here is probably the reason why multiple inheritance is impopular
      in classic Python.
  
--- 778,782 ----
      hierarchies use single inheritance, and multiple inheritance is
      usually confined to mix-in classes.  In fact, the problem shown
!     here is probably the reason why multiple inheritance is unpopular
      in classic Python.
  
***************
*** 918,922 ****
          - should we return to the old __getattr__ semantics, and
            introduce a new name (__getallattr__?) for the new semantics?
!           or introduce a new name (__getattrhook__?)for the old
            semantics?
  
--- 919,923 ----
          - should we return to the old __getattr__ semantics, and
            introduce a new name (__getallattr__?) for the new semantics?
!           or introduce a new name (__getattrhook__?) for the old
            semantics?
  
***************
*** 938,950 ****
  
      A prototype implementation of this PEP (and for PEP 252) is
!     available from CVS as a branch named "descr-branch".  To
!     experiment with this implementation, proceed to check out Python
!     from CVS according to the instructions at
!     http://sourceforge.net/cvs/?group_id=5470 but add the arguments
!     "-r descr-branch" to the cvs checkout command.  (You can also
!     start with an existing checkout and do "cvs update -r
!     descr-branch".)  For some examples of the features described here,
!     see the file Lib/test/test_descr.py and the extension module
!     Modules/xxsubtype.c.
  
  
--- 939,945 ----
  
      A prototype implementation of this PEP (and for PEP 252) is
!     available from CVS, and in the series of Python 2.2 alpha releases.
!     For some examples of the features described here, see the file
!     Lib/test/test_descr.py and the extension module Modules/xxsubtype.c.