[Python-checkins] CVS: python/nondist/peps pep-0252.txt,1.1,1.2
Guido van Rossum
gvanrossum@users.sourceforge.net
Thu, 19 Apr 2001 21:02:00 -0700
Update of /cvsroot/python/python/nondist/peps
In directory usw-pr-cvs1:/tmp/cvs-serv17416
Modified Files:
pep-0252.txt
Log Message:
Some more writing, specifying the core elements of the class-based
introspection API. I'll add attribute descriptors tomorrow.
Index: pep-0252.txt
===================================================================
RCS file: /cvsroot/python/python/nondist/peps/pep-0252.txt,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -r1.1 -r1.2
*** pep-0252.txt 2001/04/19 21:27:25 1.1
--- pep-0252.txt 2001/04/20 04:01:57 1.2
***************
*** 2,6 ****
Title: Making Types Look More Like Classes
Version: $Revision$
! Author: guido@python.org (Jeremy Hylton)
Status: Draft
Type: Standards Track
--- 2,6 ----
Title: Making Types Look More Like Classes
Version: $Revision$
! Author: guido@python.org (Guido van Rossum)
Status: Draft
Type: Standards Track
***************
*** 48,62 ****
of all attributes supported by a specific object, but in practice
two conventions have appeared that together work for almost all
! objects.
! The first API is used primarily for class instances; it is also
! used by Digital Creations's ExtensionClasses. It assumes that all
! data attributes of an object x are stored in the dictionary
! x.__dict__, and that all methods and class variables can be found
! by inspection of x's class, written as x.__class__. Classes have
! a __dict__ attribute, which yields a dictionary containing methods
! and class variables defined by the class itself, and a __bases__
! attribute, which is a tuple of base classes that must be inspected
! recursively. Some assumption here are:
- attributes defined in the instance dict override attributes
--- 48,64 ----
of all attributes supported by a specific object, but in practice
two conventions have appeared that together work for almost all
! objects. I'll call them the class-based introspection API and the
! type-based introspection API; class API and type API for short.
! The class-based introspection API is used primarily for class
! instances; it is also used by Digital Creations's
! ExtensionClasses. It assumes that all data attributes of an
! object x are stored in the dictionary x.__dict__, and that all
! methods and class variables can be found by inspection of x's
! class, written as x.__class__. Classes have a __dict__ attribute,
! which yields a dictionary containing methods and class variables
! defined by the class itself, and a __bases__ attribute, which is a
! tuple of base classes that must be inspected recursively. Some
! assumption here are:
- attributes defined in the instance dict override attributes
***************
*** 72,77 ****
left-to-right, depth-first rule for attribute search.)
! The second introspection API is supported in one form or another
! by most built-in objects. It uses two special attributes,
__members__ and __methods__. The __members__ attribute, if
present, is a list of method names supported by the object. The
--- 74,79 ----
left-to-right, depth-first rule for attribute search.)
! The type-based introspection API is supported in one form or
! another by most built-in objects. It uses two special attributes,
__members__ and __methods__. The __members__ attribute, if
present, is a list of method names supported by the object. The
***************
*** 79,86 ****
names supported by the object.
! This API is sometimes combined by a __dict__ that works the same
! was as for instances (e.g., for function objects in Python 2.1,
! f.__dict__ contains f's dynamic attributes, while f.__members__
! lists the names of f's statically defined attributes).
Some caution must be exercised: some objects don't list theire
--- 81,89 ----
names supported by the object.
! The type API is sometimes combined by a __dict__ that works the
! same was as for instances (e.g., for function objects in Python
! 2.1, f.__dict__ contains f's dynamic attributes, while
! f.__members__ lists the names of f's statically defined
! attributes).
Some caution must be exercised: some objects don't list theire
***************
*** 91,96 ****
or not.
! This second introspection API has never been carefully specified.
! It is part of folklore, and most 3rd party extensions support it
because they follow examples that support it. Also, any type that
uses Py_FindMethod() and/or PyMember_Get() in its tp_getattr
--- 94,99 ----
or not.
! The type API has never been carefully specified. It is part of
! Python folklore, and most third party extensions support it
because they follow examples that support it. Also, any type that
uses Py_FindMethod() and/or PyMember_Get() in its tp_getattr
***************
*** 98,118 ****
attribute names __methods__ and __members__, respectively.
! Digital Creations's ExtensionClasses ignore the second
! introspection API, and instead emulate the class instance
! introspection API, which is more powerful. In this PEP, I propose
! to phase out the second API in favor of supporting the class
! instance introspection API for all types.
!
! One argument in favor of the class instance introspection API is
! that it doesn't require you to create an instance in order to find
! out which attributes a type supports; this in turn is useful for
! documentation processors. For example, the socket module exports
! the SocketType object, but this currently doesn't tell us what
! methods are defined on socket objects.
- Specification
-
- XXX
-
Discussion
--- 101,253 ----
attribute names __methods__ and __members__, respectively.
! Digital Creations's ExtensionClasses ignore the type API, and
! instead emulate the class API, which is more powerful. In this
! PEP, I propose to phase out the type API in favor of supporting
! the class API for all types.
!
! One argument in favor of the class API is that it doesn't require
! you to create an instance in order to find out which attributes a
! type supports; this in turn is useful for documentation
! processors. For example, the socket module exports the SocketType
! object, but this currently doesn't tell us what methods are
! defined on socket objects. Using the class API, SocketType shows
! us exactly what the methods for socket objects are, and we can
! even extract their docstrings, without creating a socket. (Since
! this is a C extension module, the source-scanning approach to
! docstring extraction isn't feasible in this case.)
!
! Specification of the class-based introspection API
!
! Objects may have two kinds of attributes: static and dynamic. The
! names and sometimes other properties of static attributes are
! knowable by inspection of the object's type or class, which is
! accessible through obj.__class__ or type(obj). (I'm using type
! and class interchangeably, because that's the goal of the
! exercise.)
!
! (XXX static and dynamic are lousy names, because the "static"
! attributes may actually behave quite dynamically.)
!
! The names and values of dynamic properties are typically stored in
! a dictionary, and this dictionary is typically accessible as
! obj.__dict__. The rest of this specification is more concerned
! with discovering the names and properties of static attributes
! than with dynamic attributes.
!
! Examples of dynamic attributes are instance variables of class
! instances, module attributes, etc. Examples of static attributes
! are the methods of built-in objects like lists and dictionaries,
! and the attributes of frame and code objects (c.co_code,
! c.co_filename, etc.). When an object with dynamic attributes
! exposes these through its __dict__ attribute, __dict__ is a static
! attribute.
!
! In the discussion below, I distinguish two kinds of objects:
! regular objects (e.g. lists, ints, functions) and meta-objects.
! Meta-objects are types and classes. Meta-objects are also regular
! objects, but we're mostly interested in them because they are
! referenced by the __class__ attribute of regular objects (or by
! the __bases__ attribute of meta-objects).
!
! The class introspection API consists of the following elements:
!
! - the __class__ and __dict__ attributes on regular objects;
!
! - the __bases__ and __dict__ attributes on meta-objects;
!
! - precedence rules;
!
! - attribute descriptors.
!
! 1. The __dict__ attribute on regular objects
!
! A regular object may have a __dict__ attribute. If it does,
! this should be a mapping (not necessarily a dictionary)
! supporting at least __getitem__, keys(), and has_item(). This
! gives the dynamic attributes of the object. The keys in the
! mapping give attribute names, and the corresponding values give
! their values.
!
! Typically, the value of an attribute with a given name is the
! same object as the value corresponding to that name as a key in
! the __dict__. In othe words, obj.__dict__['spam'] is obj.spam.
! (But see the precedence rules below; a static attribute with
! the same name *may* override the dictionary item.)
!
! 2. The __class__ attribute on regular objects
!
! A regular object may have a __class__ attributes. If it does,
! this references a meta-object. A meta-object can define static
! attributes for the regular object whose __class__ it is.
!
! 3. The __dict__ attribute on meta-objects
!
! A meta-object may have a __dict__ attribute, of the same form
! as the __dict__ attribute for regular objects (mapping, etc).
! If it does, the keys of the meta-object's __dict__ are names of
! static attributes for the corresponding regular object. The
! values are attribute descriptors; we'll explain these later.
! (An unbound method is a 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
! bases (see below) may define additional dynamic attributes. In
! other words, mobj.spam is not always mobj.__dict__['spam'].
! (This rule contains a loophole because for classes, if
! C.__dict__['spam'] is a function, C.spam is an unbound method
! object.)
!
! 4. The __bases__ attribute on meta-objects
!
! A meta-object may have a __bases__ attribute. If it does, this
! should be a sequence (not necessarily a tuple) of other
! meta-objects, the bases. An absent __bases__ is equivalent to
! an empty sequece of bases. There must never be a cycle in the
! relationship between meta objects defined by __bases__
! attributes; in other words, the __bases__ attributes define an
! inheritance tree, where the root of the tree is the __class__
! attribute of a regular object, and the leaves of the trees are
! meta-objects without bases. The __dict__ attributes of the
! meta-objects in the inheritance tree supply attribute
! descriptors for the regular object whose __class__ is at the
! top of the inheritance tree.
!
! 5. Precedence rules
!
! When two meta-objects in the inheritance tree both define an
! attribute descriptor with the same name, the left-to-right
! depth-first rule applies. (XXX define rigorously.)
!
! When a dynamic attribute (one defined in a regular object's
! __dict__) has the same name as a static attribute (one defined
! by a meta-object in the inheritance tree rooted at the regular
! object's __class__), the dynamic attribute *usually* wins, but
! for some attributes the meta-object may specify that the static
! attribute overrides the dynamic attribute.
!
! (We can't have a simples rule like "static overrides dynamic"
! or "dynamic overrides static", because some static attributes
! indeed override dynamic attributes, e.g. a key '__class__' in
! an instance's __dict__ is ignored in favor of the statically
! defined __class__ pointer, but on the other hand most keys in
! inst.__dict__ override attributes defined in inst.__class__.
! The mechanism whereby a meta-object can specify that a
! particular attribute has precedence is not yet specified.)
!
! 6. Attribute descriptors
!
! XXX
!
! The introspection API is a read-only API. We don't define the
! effect of assignment to any of the special attributes (__dict__,
! __class__ and __bases__), nor the effect of assignment to the
! items of a __dict__. Generally, such assignments should be
! considered off-limits. An extension of this PEP may define some
! semantics for some such assignments. (Especially because
! currently instances support assignment to __class__ and __dict__,
! and classes support assignment to __bases__ and __dict__.)
Discussion
***************
*** 142,145 ****
--- 277,284 ----
XXX
+
+ Copyright
+
+ This document has been placed in the public domain.