[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.