Added attribute descriptor API.

Still need to do the signature object API.
This commit is contained in:
Guido van Rossum 2001-04-23 21:19:03 +00:00
parent 75110765c1
commit 701fba5cdb
1 changed files with 94 additions and 0 deletions

View File

@ -24,6 +24,7 @@ Abstract
describe a method, a typed field in the object structure, or a
generalized attribute represented by getter and setter functions.
Introduction
One of Python's oldest language warts is the difference between
@ -39,6 +40,7 @@ Introduction
more like types, and subclassing from built-in types; these topics
are not on the table for this PEP.
Introspection APIs
Introspection concerns itself with finding out what attributes an
@ -115,6 +117,7 @@ Introspection APIs
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
@ -273,8 +276,99 @@ Specification of the class-based introspection API
currently instances support assignment to __class__ and __dict__,
and classes support assignment to __bases__ and __dict__.)
Specification of the attribute descriptor API
Attribute descriptors have the following attributes. In the
examples, x is an object, C is x.__class__, x.meth() is a method,
and x.ivar is a data attribute or instance variable.
- name: the original attribute name. Note that because of
aliasing and renaming, the attribute may be known under a
different name, but this is the name under which it was born.
Example: C.meth.name == 'meth'.
- doc: the attribute's documentation string.
- objclass: the class that declared this attribute. The
descriptor only applies to objects that are instances of this
class (this includes instances of its subclasses). Example:
C.meth.objclass is C.
- kind: either "method" or "data". This distinguishes between
methods and data attributes. The primary operation on a method
attribute is to call it. The primary operations on a data
attribute are to get and to set it. Example: C.meth.kind ==
'method'; C.ivar.kind == 'data'.
- default: for optional data attributes, this gives a default or
initial value. XXX Python has two kinds of semantics for
referencing "absent" attributes: this may raise an
AttributeError, or it may produce a default value stored
somewhere in the class. There could be a flag that
distinguishes between these two cases. Also, there could be a
flag that tells whether it's OK to delete an attribute (and what
happens then -- a default value takes its place, or it's truly
gone).
- attrclass: for data attributes, this can be the class of the
attribute value, or None. If this is not None, the attribute
value is restricted to being an instance of this class (or of a
subclass thereof). If this is None, the attribute value is not
constrained. For method attributes, this should normally be
None (a class is not sufficient information to describe a method
signature). If and when optional static typing is added to
Python, this the meaning of this attribute may change to
describe the type of the attribute.
- signature: for methods, an object that describes the signature
of the method. Signature objects will be described further
below.
- readonly: Boolean indicating whether assignment to this
attribute is disallowed. This is usually true for methods.
Example: C.meth.readonly == 1; C.ivar.kind == 0.
- get(): a function of one argument that retrieves the attribute
value from an object. Examples: C.ivar.get(x) ~~ x.ivar;
C.meth.get(x) ~~ x.meth.
- set(): a function of two arguments that sets the attribute value
on the object. If readonly is set, this method raises a
TypeError exception. Example: C.ivar.set(x, y) ~~ x.ivar = y.
- call(): for method descriptors, this is a function of at least
one argument that calls the method. The first argument is the
object whose method is called; the remaining arguments
(including keyword arguments) are passed on to the method.
Example: C.meth.call(x, 1, 2) ~~ x.meth(1, 2).
- bind(): for method descriptiors, this is a function of one
argument that returns a "bound method object". This in turn can
be called exactly like the method should be called (in fact this
is what is returned for a bound method). This is the same as
get(). Example: C.meth.bind(x) ~~ x.meth.
For convenience, __name__ and __doc__ are defined as aliases for
name and doc. Also for convenience, calling the descriptor can do
one of three things:
- Calling a method descriptor is the same as calling its call()
method. Example: C.meth(x, 1, 2) ~~ x.meth(1, 2).
- Calling a data descriptor with one argument is the same as
calling its get() method. Example: C.ivar(x) ~~ x.ivar.
- Calling a data descriptor with two arguments is the same as
calling its set() method. Example: C.ivar(x, y) ~~ x.ivar = y.
Note that this specification does not define how to create
specific attribute descriptors. This is up to the individual
attribute descriptor implementations, of which there may be many.
Specification of the signature object API
XXX
Discussion