<h5> which we can use just like an ordinary attribute:</h5>
<p> p=Point(2,2)
print p.radius</p>
<h3> Overriding method calls</h3>
<p> Normally, when a method is called, the function wrapped by the
method is called directly by the method. In some cases, it is
useful for user-defined logic to participate in the actual
function call. Extension classes introduce a new protocol that
provides extension classes greater control over how their
methods are called. If an extension class defines a special
method, <code>__call_method__</code>, then this method will be called to
call the functions (or other callable object) wrapped by the
method. The method. <code>__call_method__</code> should provide the same
interface as provided by the Python builtin <code>apply</code> function.</p>
<p> For example, consider the expression: <code>x.meth(arg1, arg2)</code>. The
expression is evaluated by first computing a method object that
wraps <code>x</code> and the attribute of <code>x</code> stored under the name <code>meth</code>.
Assuming that <code>x</code> has a <code>__call_method__</code> method defined, then
the <code>__call_method__</code> method of <code>x</code> will be called with two
arguments, the attribute of <code>x</code> stored under the name <code>meth</code>,
and a tuple containing <code>x</code>, <code>arg1</code>, and <code>arg2</code>.</p>
<p> To see how this feature may be used, see the Python module,
<code>Syn.py</code>, which is included in the ExtensionClass distribution.
This module provides a mix-in class that provides Java-like
"synchonized" classes that limit access to their methods to one
thread at a time.</p>
<p> An interesting application of this mechanism would be to
implement interface checking on method calls.</p>
<h3> Method attributes</h3>
<p> Methods of ExtensionClass instances can have user-defined
attributes, which are stored in their associated instances.</p>
<p> For example:
<pre>
class C(ExtensionClass.Base):
def get_secret(self):
"Get a secret"
....
c=C()
c.f.__roles__=['Trusted People']
print c.f.__roles__ # outputs ['Trusted People']
print c.f__roles__ # outputs ['Trusted People']
print C.f.__roles__ # fails, unbound method
</pre>
</p>
<p> A bound method attribute is set by setting an attribute in it's
instance with a name consisting of the concatination of the
method's <code>__name__</code> attribute and the attribute name.
Attributes cannot be set on unbound methods.</p>
<h3> Class initialization</h3>
<p> Normal Python class initialization is similar to but subtley
different from instance initialization. An instance <code>__init__</code>
function is called on an instance immediately <em>after</em> it is
created. An instance <code>__init__</code> function can use instance
information, like it's class and can pass the instance to other
functions. On the other hand, the code in class statements is
executed immediately <em>before</em> the class is created. This means
that the code in a class statement cannot use class attributes,
like <code>__bases__</code>, or pass the class to functions.</p>
<p> Extension classes provide a mechanism for specifying code to be
run <em>after</em> a class has been created. If a class or one of it's
base classes defines a <code>__class_init__</code> method, then this method
will be called just after a class has been created. The one
argument passed to the method will be the class, <em>not</em> an
instance of the class.</p>
<h2> Useful macros defined in ExtensionClass.h</h2>
<p> A number of useful macros are defined in ExtensionClass.h.
These are documented in <code>ExtensionClass.h</code>.</p>
<h2> Pickleability</h2>
<p> Classes created with ExtensionClass, including extension base
classes are automatically pickleable. The usual gymnastics
necessary to pickle <code>non-standard</code> types are not necessray for
types that have been modified to be extension base classes.</p>
<h2> Status</h2>
<p> The current release of the extension class module is <ahref="http://www.digicool.com/releases/ExtensionClass/ExtensionClass-1.1.tar.gz">1.1</a>.
The core implementation has less than four thousand lines of code,
including comments. This release requires Python 1.4 or higher.</p>
<p> To find out what's changed in this release, see the
<ahref="release.html">release notes</a>.</p>
<p><ahref="Installation.html">Installation instructions</a>, are provided.</p>
<h2> Issues</h2>
<p> There are a number of issues that came up in the course of this work
and that deserve mention.</p>
<ul>
<li>In Python 1.4, the class extension mechanism described in <ahref="#ref4">[4]</a> required
that the first superclass in a list of super-classes must be of the
extended class type. This may not be convenient if mix-in
behavior is desired. If a list of base classes starts with a
standard python class, but includes an extension class, then an
error was raised. It would be more useful if, when a list of base
classes contains one or more objects that are not python classes,
the first such object was used to control the extended class
definition. To get around this, the <code>ExtensionClass</code> module exports
a base extension class, <code>Base</code>, that can be used as the first base
class in a list of base classes to assure that an extension
subclass is created.<p> Python 1.5 allows the class extension even if the first non-class
object in the list of base classes is not the first object in
the list. This issue appears to go away in Python 1.5, however,
the restriction that the first non-class object in a list of
base classes must be the first in the list may reappear in later
versions of Python.</p>
</li>
<li>Currently, only one base extension class can define any data in
C. The data layout of subclasses-instances is the same as for the
base class that defines data in C, except that the data structure
is extended to hold an instance dictionary. The data structure
begins with a standard python header, and extension methods expect
the C instance data to occur immediately after the object header. If
two or more base classes defined C data, the methods for the
different base classes would expect their data to be in the same
location. A solution might be to allocate base class instances and
store pointers to these instances in the subclass data structure.
The method binding mechanism would have to be a more complicated
to make sure that methods were bound to the correct base data
structure. Alternatively, the signature of C methods could be
expanded to allow pointers to expected class data to be passed
in addition to object pointers.</li>
<li>There is currently no support for sub-classing in C, beyond that
provided by method chains.</li>
<li>Rules for mixed-type arithmetic are different for python class
instances than they are for extension type instances. Python
classes can define right and left versions of numeric binary
operators, or they can define a coercion operator for converting
binary operator operands to a common type. For extension types,
only the latter, coercion-based, approach is supported. The
coercion-based approach does not work well for many data types for
which coercion rules depend on the operator. Because extension
classes are based on extension types, they are currently limited
to the coercion-based approach. It should be possible to
extend the extension class implementation to allow both types of
mixed-type arithmetic control.</li>
<li>I considered making extension classes immutable, meaning that
class attributes could not be set after class creation. I also
considered making extension subclasses cache inherited
attributes. Both of these are related and attractive for some
applications, however, I decided that it would be better to retain
standard class instance semantics and provide these features as
options at a later time.</li>
<li>The extension class module defines new method types to bind C and
python methods to extension class instances. It would be useful
for these method objects to provide access to function call
information, such as the number and names of arguments and the
number of defaults, by parsing extension function documentation
strings.</li>
</ul>
<h2> Applications</h2>
<p> Aside from test and demonstration applications, the extension class
mechanism has been used to provide an extension-based implementation
of the persistence mechanism described in <ahref="#ref1">[1]</a>. We have developed
this further to provide features such as automatic deactivation of
objects not used after some period of time and to provide more
efficient persistent-object cache management.</p>
<p> Acquisition has been heavily used in our recent products.
Synchonized classes have also been used in recent products.</p>
<h2> Summary</h2>
<p> The extension-class mechanism described here provides a way to add
class services to extension types. It allows:
<ul>
<li>Sub-classing extension classes in Python,</li>
<li>Construction of extension class instances by calling extension
classes,</li>
<li>Extension classes to provide meta-data, such as unbound methods
and their documentation string.</li>
</ul>
</p>
<p> In addition, the extension class module provides a relatively
concise example of the use of mechanisms that were added to Python
to support MESS <ahref="#ref6">[6]</a>, and that were described at the fourth Python
Workshop <ahref="#ref4">[4]</a>. It is hoped that this will spur research in improved
and specialized models for class implementation in Python.</p>
<p> References</p>
<p><aname="ref1">[1]</a> Fulton, J., <ahref="http://www.digicool.com/papers/Persistence.html">Providing Persistence for World-Wide-Web Applications</a>,
Proceedings of the 5th Python Workshop.</p>
<p><aname="ref2">[2]</a> Page, R. and Cropper, S., <ahref="http://www.digicool.com/papers/DocumentTemplate.html">Document Template</a>,
Proceedings of the 5th Python Workshop.</p>
<p><aname="ref3">[3]</a> Beaudry, D., <ahref="http://www.python.org/workshops/1994-11/BuiltInClasses/BuiltInClasses_1.html">Deriving Built-In Classes in Python</a>,
Proceedings of the First International Python Workshop.</p>
<p><aname="ref4">[4]</a> Van Rossum, G., <ahref="http://www.python.org/workshops/1996-06/notes/thursday.html">Don Beaudry Hack - MESS</a>,
presented in the Developer's Future Enhancements session of the