summaryrefslogtreecommitdiff
path: root/pypers/classinitializer/classinitializer.tex
diff options
context:
space:
mode:
Diffstat (limited to 'pypers/classinitializer/classinitializer.tex')
-rw-r--r--pypers/classinitializer/classinitializer.tex696
1 files changed, 696 insertions, 0 deletions
diff --git a/pypers/classinitializer/classinitializer.tex b/pypers/classinitializer/classinitializer.tex
new file mode 100644
index 0000000..1ff223d
--- /dev/null
+++ b/pypers/classinitializer/classinitializer.tex
@@ -0,0 +1,696 @@
+\documentclass[10pt,a4paper,english]{article}
+\usepackage{babel}
+\usepackage{ae}
+\usepackage{aeguill}
+\usepackage{shortvrb}
+\usepackage[latin1]{inputenc}
+\usepackage{tabularx}
+\usepackage{longtable}
+\setlength{\extrarowheight}{2pt}
+\usepackage{amsmath}
+\usepackage{graphicx}
+\usepackage{color}
+\usepackage{multirow}
+\usepackage{ifthen}
+\usepackage[colorlinks=true,linkcolor=blue,urlcolor=blue]{hyperref}
+\usepackage[DIV12]{typearea}
+%% generator Docutils: http://docutils.sourceforge.net/
+\newlength{\admonitionwidth}
+\setlength{\admonitionwidth}{0.9\textwidth}
+\newlength{\docinfowidth}
+\setlength{\docinfowidth}{0.9\textwidth}
+\newlength{\locallinewidth}
+\newcommand{\optionlistlabel}[1]{\bf #1 \hfill}
+\newenvironment{optionlist}[1]
+{\begin{list}{}
+ {\setlength{\labelwidth}{#1}
+ \setlength{\rightmargin}{1cm}
+ \setlength{\leftmargin}{\rightmargin}
+ \addtolength{\leftmargin}{\labelwidth}
+ \addtolength{\leftmargin}{\labelsep}
+ \renewcommand{\makelabel}{\optionlistlabel}}
+}{\end{list}}
+\newlength{\lineblockindentation}
+\setlength{\lineblockindentation}{2.5em}
+\newenvironment{lineblock}[1]
+{\begin{list}{}
+ {\setlength{\partopsep}{\parskip}
+ \addtolength{\partopsep}{\baselineskip}
+ \topsep0pt\itemsep0.15\baselineskip\parsep0pt
+ \leftmargin#1}
+ \raggedright}
+{\end{list}}
+% begin: floats for footnotes tweaking.
+\setlength{\floatsep}{0.5em}
+\setlength{\textfloatsep}{\fill}
+\addtolength{\textfloatsep}{3em}
+\renewcommand{\textfraction}{0.5}
+\renewcommand{\topfraction}{0.5}
+\renewcommand{\bottomfraction}{0.5}
+\setcounter{totalnumber}{50}
+\setcounter{topnumber}{50}
+\setcounter{bottomnumber}{50}
+% end floats for footnotes
+% some commands, that could be overwritten in the style file.
+\newcommand{\rubric}[1]{\subsection*{~\hfill {\it #1} \hfill ~}}
+\newcommand{\titlereference}[1]{\textsl{#1}}
+% end of "some commands"
+\input{style.tex}
+\title{Let's keep it simple (or, how to do metaprogramming without metaclasses)}
+\author{}
+\date{}
+\hypersetup{
+pdftitle={Let's keep it simple (or, how to do metaprogramming without metaclasses)},
+pdfauthor={Michele Simionato}
+}
+\raggedbottom
+\begin{document}
+\maketitle
+
+%___________________________________________________________________________
+\begin{center}
+\begin{tabularx}{\docinfowidth}{lX}
+\textbf{Author}: &
+ Michele Simionato \\
+\textbf{Date}: &
+ 10 July 2006 \\
+\textbf{Version}: &
+ 0.5 \\
+\end{tabularx}
+\end{center}
+
+\setlength{\locallinewidth}{\linewidth}
+\hypertarget{contents}{}
+\pdfbookmark[0]{Contents}{contents}
+\subsubsection*{~\hfill Contents\hfill ~}
+\begin{list}{}{}
+\item {} \href{\#introduction}{Introduction}
+
+\item {} \href{\#about-class-initialization}{About class initialization}
+
+\item {} \href{\#please-stop-abusing-metaclasses}{Please stop abusing metaclasses}
+
+\item {} \href{\#the-classinitializer-decorator}{The \texttt{classinitializer} decorator}
+
+\item {} \href{\#tricky-points-and-caveats}{Tricky points and caveats}
+
+\item {} \href{\#example-initializing-records}{Example: initializing records}
+
+\item {} \href{\#references}{References}
+
+\item {} \href{\#questions-and-answers}{Questions and answers}
+
+\end{list}
+
+
+
+%___________________________________________________________________________
+
+\hypertarget{introduction}{}
+\pdfbookmark[0]{Introduction}{introduction}
+\section*{Introduction}
+
+A few days ago I was at CERN, at the EuroPython 2006 conference. The
+conference was good, the organization perfect, the talks of
+very high level, the people extremely nice.
+
+Nevertheless, I saw a trend growing in the Python community
+that disturbed me a little and motivated
+me to write this paper. The trend I am alluding to, is the trend
+towards \emph{cleverness}. Unfortunately, whereas once cleverness was
+mostly confined to Zope and Twisted, now is appearing everywhere.
+
+I personally don't have anything against cleverness for
+experimental projects and learning exercises. But I have a gripe
+against cleverness when I see it deployed in production frameworks
+that I am forced to cope with as an user.
+
+Cleverness means making things more complicated than
+needed, making things more fragile, making the learning curve
+steeper and, worse of all, making debugging harder.
+
+In this short paper I will try to give my small contribution against
+cleverness, at least in a case where I have some expertise, i.e.
+against metaclass abuses.
+
+Let me say that I consider \emph{metaclass abuse} any usage of a metaclass
+in a situation where you could have solved the problem without a
+metaclass.
+
+I feel in part responsible for some of the abuses I see floating
+around in newsgroups, in conferences and in frameworks source code,
+because of my (together with David Mertz) contribution in popularizing
+metaclasses, so I have decided to make amend with this paper.
+
+This paper consider only one kind of metaprogramming technique, i.e.
+the creation at runtime of classes with attributes and methods which
+are dynamically generated. Contrarily to popular belief, this is a job
+where most of the time you \emph{don't need} and you \emph{don't want} a custom
+metaclass, as I will argue in the next section.
+
+The paper is intended for a double target of readers:
+\begin{itemize}
+\item {}
+average programmers, that would benefit from knowing a few
+meta-programming tricks, but are scared off by brain melting concepts;
+
+\item {}
+clever programmers, which are actually too clever and should know
+better [\hyperlink{id2}{1}].
+
+\end{itemize}
+
+If you are a lazy reader, your may just read the next paragraph and
+the last one, and forget about the details.
+\begin{figure}[b]\hypertarget{id2}[1]
+The problem is that it is easy to be clever whereas it takes a
+lot of time to become unclever. For instance, it took me a few
+months to understand how to use metaclasses, but a few years
+to understand how \emph{not} to use them.
+\end{figure}
+
+
+%___________________________________________________________________________
+
+\hypertarget{about-class-initialization}{}
+\pdfbookmark[0]{About class initialization}{about-class-initialization}
+\section*{About class initialization}
+
+By class initialization I mean setting attributes and methods of
+classes immediately after their creation, once and for all [\hyperlink{id4}{2}].
+
+There are various common situations where a programmer may want to
+initialize her classes: for instance, she may want to set some default class
+attributes according to parameters read from a configuration
+file, or she may want to set class properties according to the fields
+in a database table.
+
+The easiest way to perform class initialization
+is by using an imperative style: one first creates the class,
+and then adds the dynamically generated methods and attributes.
+
+For instance, if the problem is to generate properties for an \texttt{Article}
+record class, an imperative solution is something like the following:
+\begin{quote}{\ttfamily \raggedright \noindent
+class~Article(object):~\\
+~~~def~somemethod(self):~\\
+~~~~~~~pass~\\
+~~~...~\\
+~\\
+set{\_}properties(Article,~{[}('title',~str),~('author',~str),~('date',~date){]})
+}\end{quote}
+
+However, since (proper) class initialization should occur only once,
+it does not need to be distinguished by class
+creation, and it may be argued that it
+should be treated with a declarative style, with a syntax like the following:
+\begin{quote}{\ttfamily \raggedright \noindent
+class~Article(object):~\\
+~\\
+~~~def{\_}properties({[}('title',~str),~('author',~str),~('date',~date){]})~\\
+~\\
+~~~def~somemethod(self):~\\
+~~~~~~~pass~\\
+~\\
+~~~...
+}\end{quote}
+
+This paper is about providing a generic facility to define \emph{class initializers}
+to be used in the class scope, such as \texttt{def{\_}properties}.
+
+\textbf{Disclaimer:} the advantage of the solution I propose here,
+is that it works in current Python and it is less clever than
+metaclasses, Still I would consider it a little too clever. A clean solution
+to the problem would be to add class decorator to the language. That
+would allow a syntax like the following:
+\begin{quote}{\ttfamily \raggedright \noindent
+@with{\_}properties({[}('title',~str),~('author',~str),~('date',~date){]})~\\
+class~Article(object):~\\
+~~~def~somemethod(self):~\\
+~~~~~~~pass~\\
+~~~...
+}\end{quote}
+
+However, it is not sure at the moment if and when Guido will add class
+decorators, so my proposed solution is the lesser of two evils.
+\begin{figure}[b]\hypertarget{id4}[2]
+Well, in Python methods and attributes can always be changed at
+a later time, but let us assume that nobody is cheating here.
+\end{figure}
+
+
+%___________________________________________________________________________
+
+\hypertarget{please-stop-abusing-metaclasses}{}
+\pdfbookmark[0]{Please stop abusing metaclasses}{please-stop-abusing-metaclasses}
+\section*{Please stop abusing metaclasses}
+
+Everybody knows how to initialize instances. One just overrides
+the class \texttt{{\_}{\_}init{\_}{\_}} method. Since classes are instances of metaclasses,
+the natural solution to the class initialization problem seems to be
+to use a custom metaclass and to override its \texttt{{\_}{\_}init{\_}{\_}} method.
+
+Un fortunately, things are not so easy, because of inheritance. The
+issue is that once you have defined a custom metaclass for your base
+class, all the derived classes will inherit the metaclass, so the
+initialization code will be run on all derived classes, magically and
+implicitly.
+
+That may be fine in specific circumstances (for instance,
+suppose you have to register in your framework all the classes you
+define: using a metaclass ensures that you cannot forget to register a
+derived class), however, in many cases you may not like this behavior because:
+\newcounter{listcnt0}
+\begin{list}{\arabic{listcnt0}.}
+{
+\usecounter{listcnt0}
+\setlength{\rightmargin}{\leftmargin}
+}
+\item {}
+you may believe that \emph{explicit is better than implicit};
+
+\item {}
+if the derived classes have the same dynamic class attributes of
+the base class, implicitly setting them again for each derived
+class is a waste, since they would be available anyway by
+inheritance. This may be a real issue if the initialization code is
+slow, possibly because it must access a database, or perform some
+heavy computation: in this case one must add a check in the
+metaclass code to see if the attributes were already set in
+a parent class, but this adds plumbing and it does not give real
+control on a per-class basis;
+
+\item {}
+a custom metaclass will make your classes somewhat magic and
+nonstandard: you may not want to increase your chances to incur in
+metaclass conflicts, issues with \texttt{{\_}{\_}slots{\_}{\_}}, fights with (Zope)
+extension classes and other guru-level intricacies [\hyperlink{id6}{3}];
+
+\item {}
+you feel that a custom metaclasses is overkill for the simple job
+of class initialization and you would rather use a simpler solution.
+
+\end{list}
+
+In other words,you should use a custom metaclass only when your real
+intention is to have code running on derived classes without users of
+those classes noticing it. If this is not your case, please don't a
+metaclass and make your life (as well your users) happier.
+\begin{figure}[b]\hypertarget{id6}[3]
+Metaclasses are more fragile than many people realize. I
+personally have never used them for production code, even
+after four years of usage in experimental code.
+\end{figure}
+
+
+%___________________________________________________________________________
+
+\hypertarget{the-classinitializer-decorator}{}
+\pdfbookmark[0]{The classinitializer decorator}{the-classinitializer-decorator}
+\section*{The \texttt{classinitializer} decorator}
+
+The aim of this paper is to provide a decorator called
+\texttt{classinitializer} that can be used to define
+class initializers, i.e. procedures taking classes and setting their
+attributes and methods. In order to be concrete, consider the following
+class initializer example:
+\begin{quote}{\ttfamily \raggedright \noindent
+def~set{\_}defaults(cls,~**kw):~\\
+~~~~for~k,~v~in~kw.iteritems():~\\
+~~~~~~~~setattr(cls,~k,~v)
+}\end{quote}
+
+You may use it imperatively, right after a class definition:
+\begin{quote}{\ttfamily \raggedright \noindent
+class~ClassToBeInitialized(object):~\\
+~~~~pass~\\
+~\\
+set{\_}defaults(ClassToBeInitialized,~a=1,~b=2)
+}\end{quote}
+
+However the imperative solution has a few drawbacks:
+\setcounter{listcnt0}{0}
+\begin{list}{\arabic{listcnt0}.}
+{
+\usecounter{listcnt0}
+\setlength{\rightmargin}{\leftmargin}
+}
+\item {}
+it does not comply with DRY, i.e. the class name is repeated
+and if I change it during refactoring, I have to change it (at
+least) twice;
+
+\item {}
+readability is suboptimal: since class definition and class
+initialization are separated, for long class definitions I may end
+up not seeing the last line;
+
+\item {}
+it feels wrong to first define something and immediately right
+after to mutate it.
+
+\end{list}
+
+Luckily, the \texttt{classinitializer} decorator provides a much nicer
+declarative solution. The decorator performs some deep magic and converts
+\texttt{set{\_}defaults(cls, **kw)} into a function that can be
+used at the top scope into a class definition, with the current class
+automagically passed as first parameter:
+\begin{verbatim}>>> @classinitializer # add magic to set_defaults
+... def set_defaults(cls, **kw):
+... for k, v in kw.iteritems():
+... setattr(cls, k, v)\end{verbatim}
+\begin{verbatim}>>> class ClassToBeInitialized(object):
+... set_defaults(a=1, b=2)\end{verbatim}
+\begin{verbatim}>>> ClassToBeInitialized.a
+1
+>>> ClassToBeInitialized.b
+2\end{verbatim}
+
+If you have used Zope interfaces, you may have seen examples of class
+initializers (I mean \texttt{zope.interface.implements}). In fact under the hood
+\texttt{classinitializer} is implemented by using a trick copied from
+\texttt{zope.interface.advice}, which credits Phillip J. Eby. The trick
+uses the \texttt{{\_}{\_}metaclass{\_}{\_}} hook, but it \emph{does not use} a custom
+metaclass, so that in this example \texttt{ClassToBeInitialized} will
+continue to keep its original metaclass, i.e. the plain old regular
+built-in metaclass \texttt{type} of new style classes:
+\begin{verbatim}>>> type(ClassToBeInitialized)
+<type 'type'>\end{verbatim}
+
+In principle, the trick also works for old style classes,
+and it would be easy to write an implementation keeping old style
+classes old style. However, since according to Guido himself
+\emph{old style classes are morally deprecated}, the current implementation
+automagically converts old style classes into new style classes:
+\begin{verbatim}>>> class WasOldStyle:
+... set_defaults(a=1, b=2)\end{verbatim}
+\begin{verbatim}>>> WasOldStyle.a, WasOldStyle.b
+(1, 2)
+>>> type(WasOldStyle)
+<type 'type'>\end{verbatim}
+
+One of the motivations for the \texttt{classinitializer} decorator, is to hide the
+plumbing, and to make mere mortals able to implements their own
+class initializers in an easy way, without knowing the details of
+how class creation works and the secrets of the \texttt{{\_}{\_}metaclass{\_}{\_}}
+hook. The other motivation, is that even for Python wizards it is very
+unconvenient to rewrite the code managing the \texttt{{\_}{\_}metaclass{\_}{\_}} hook
+every time one writes a new class initializer. So I have decided to
+use a decorator to allow separation of concerns and reuse of code.
+
+As a final note, let me point out that the decorated version of
+\texttt{set{\_}defaults} is so smart that it will continue to
+work as the non-decorated version outside a class scope, provided that
+you pass to it an explicit class argument.
+\begin{verbatim}>>> set_defaults(WasOldStyle, a=2)
+>>> WasOldStyle.a
+2\end{verbatim}
+
+In other words, you \emph{might} continue to use the imperative style.
+
+Here is the code for \texttt{classinitializer} (the point being that you
+don't need to be able to understand it to use the decorator):
+\begin{quote}{\ttfamily \raggedright \noindent
+{\#}<{\_}main.py>~\\
+~\\
+import~sys~\\
+~\\
+def~classinitializer(proc):~\\
+~~{\#}~basic~idea~stolen~from~zope.interface.advice,~which~credits~P.J.~Eby~\\
+~~def~newproc(*args,~**kw):~\\
+~~~~~~frame~=~sys.{\_}getframe(1)~\\
+~~~~~~if~'{\_}{\_}module{\_}{\_}'~in~frame.f{\_}locals~and~not~{\textbackslash}~\\
+~~~~~~~~~'{\_}{\_}module{\_}{\_}'~in~frame.f{\_}code.co{\_}varnames:~{\#}~we~are~in~a~class~\\
+~~~~~~~~~~if~'{\_}{\_}metaclass{\_}{\_}'~in~frame.f{\_}locals:~\\
+~~~~~~~~~~~~raise~SyntaxError("Don't~use~two~class~initializers~or{\textbackslash}n"~\\
+~~~~~~~~~~~~"a~class~initializer~together~with~a{\_}{\_}metaclass{\_}{\_}~hook")~\\
+~~~~~~~~~~def~makecls(name,~bases,~dic):~\\
+~~~~~~~~~~~~~try:~\\
+~~~~~~~~~~~~~~~~cls~=~type(name,~bases,~dic)~\\
+~~~~~~~~~~~~~except~TypeError,~e:~\\
+~~~~~~~~~~~~~~~~if~"can't~have~only~classic~bases"~in~str(e):~\\
+~~~~~~~~~~~~~~~~~~~cls~=~type(name,~bases~+~(object,),~dic)~\\
+~~~~~~~~~~~~~~~~else:~{\#}~other~strange~errors,~such~as~{\_}{\_}slots{\_}{\_}~conflicts,~etc~\\
+~~~~~~~~~~~~~~~~~~~raise~\\
+~~~~~~~~~~~~~proc(cls,~*args,~**kw)~\\
+~~~~~~~~~~~~~return~cls~\\
+~~~~~~~~~~frame.f{\_}locals{[}"{\_}{\_}metaclass{\_}{\_}"{]}~=~makecls~\\
+~~~~~~else:~\\
+~~~~~~~~~~proc(*args,~**kw)~\\
+~~newproc.{\_}{\_}name{\_}{\_}~=~proc.{\_}{\_}name{\_}{\_}~\\
+~~newproc.{\_}{\_}module{\_}{\_}~=~proc.{\_}{\_}module{\_}{\_}~\\
+~~newproc.{\_}{\_}doc{\_}{\_}~=~proc.{\_}{\_}doc{\_}{\_}~\\
+~~newproc.{\_}{\_}dict{\_}{\_}~=~proc.{\_}{\_}dict{\_}{\_}~\\
+~~return~newproc~\\
+~\\
+{\#}</{\_}main.py>
+}\end{quote}
+
+From the implementation it is clear how class initializers work:
+when you call a class initializer inside a class, your are actually defining a
+\texttt{{\_}{\_}metaclass{\_}{\_}} hook that will be called by
+the class' metaclass (typically \texttt{type}). The
+metaclass will create the class (as a new style one) and
+will pass it to the class initializer procedure.
+
+
+%___________________________________________________________________________
+
+\hypertarget{tricky-points-and-caveats}{}
+\pdfbookmark[0]{Tricky points and caveats}{tricky-points-and-caveats}
+\section*{Tricky points and caveats}
+
+Since class initializers (re)define the \texttt{{\_}{\_}metaclass{\_}{\_}} hook,
+they don't play well with classes that define a \texttt{{\_}{\_}metaclass{\_}{\_}} hook
+explicitly (as opposed to implicitly inheriting one). The issue is
+that if a \texttt{{\_}{\_}metaclass{\_}{\_}} hook is defined \emph{after} the
+class initializer, it \emph{silently} overrides it.
+\begin{verbatim}>>> class C:
+... set_defaults(a=1)
+... def __metaclass__(name, bases, dic):
+... cls = type(name, bases, dic)
+... print 'set_defaults is silently ignored'
+... return cls
+...
+set_defaults is silently ignored
+>>> C.a
+Traceback (most recent call last):
+ ...
+AttributeError: type object 'C' has no attribute 'a'\end{verbatim}
+
+This is unfortunate, but there is no general solution to this issue, and I will
+simply document it (this is one of the reasons why I feel
+class initializers to be a clever hack that should be dismissed if we
+had class decorators).
+
+On the other hand, if you call a class initializer
+\emph{after} the \texttt{{\_}{\_}metaclass{\_}{\_}} hook, you will get an exception:
+\begin{verbatim}>>> class C:
+... def __metaclass__(name, bases, dic):
+... cls = type(name, bases, dic)
+... print 'calling explicit __metaclass__'
+... return cls
+... set_defaults(a=1)
+...
+Traceback (most recent call last):
+ ...
+SyntaxError: Don't use two class initializers or
+a class initializer together with a__metaclass__ hook\end{verbatim}
+
+I feel raising an error is preferable to silently overriding your
+explicit \texttt{{\_}{\_}metaclass{\_}{\_}} hook. As a consequence, you will get an
+error if you try to use two class initializers at the same time, or
+if you call twice the same one:
+\begin{verbatim}>>> class C:
+... set_defaults(a=1)
+... set_defaults(b=2)
+Traceback (most recent call last):
+ ...
+SyntaxError: Don't use two class initializers or
+a class initializer together with a__metaclass__ hook\end{verbatim}
+
+I feel raising an error to be better than having the second
+initializer overriding the first one, i.e. in this example
+to set the \texttt{b} attribute \emph{without} setting the \texttt{a} attribute,
+which would be very confusing.
+
+Finally, let me show that there are no issues for inherited
+\texttt{{\_}{\_}metaclass{\_}{\_}} hooks and for custom metaclasses:
+\begin{verbatim}>>> class B: # a base class with a custom metaclass
+... class __metaclass__(type):
+... pass\end{verbatim}
+\begin{verbatim}>>> class C(B): # a class with both a custom metaclass AND a class initializer
+... set_defaults(a=1)\end{verbatim}
+\begin{verbatim}>>> C.a
+1
+>>> type(C)
+<class '_main.__metaclass__'>\end{verbatim}
+
+The class initializer does not disturb the metaclass of \texttt{C}, which is
+the one inherited by its base \texttt{B}, and the inherited metaclass does
+not disturb the class initializer, which does its job just fine.
+You would have run into trouble, instead, if you tried to call \texttt{set{\_}defaults}
+directly in the base class.
+
+
+%___________________________________________________________________________
+
+\hypertarget{example-initializing-records}{}
+\pdfbookmark[0]{Example: initializing records}{example-initializing-records}
+\section*{Example: initializing records}
+
+In this section I will finally discuss the example I gave at the
+beginning, about how to define record classes with a class initializer.
+Here is the code for the class initializer, plus an helper function
+for managing dates:
+\begin{quote}{\ttfamily \raggedright \noindent
+{\#}<{\_}main.py>~\\
+~\\
+import~datetime~\\
+~\\
+@classinitializer~\\
+def~def{\_}properties(cls,~schema):~\\
+~~~~"{}"{}"~\\
+~~~~Add~properties~to~cls,~according~to~the~schema,~which~is~a~list~\\
+~~~~of~pairs~(fieldname,~typecast).~A~typecast~is~a~\\
+~~~~callable~converting~the~field~value~into~a~Python~type.~\\
+~~~~The~initializer~saves~the~attribute~names~in~a~list~cls.fields~\\
+~~~~and~the~typecasts~in~a~list~cls.types.~Instances~of~cls~are~expected~\\
+~~~~to~have~private~attributes~with~names~determined~by~the~field~names.~\\
+~~~~"{}"{}"~\\
+~~~~cls.fields~=~{[}{]}~\\
+~~~~cls.types~=~{[}{]}~\\
+~~~~for~name,~typecast~in~schema:~\\
+~~~~~~~~if~hasattr(cls,~name):~{\#}~avoid~accidental~overriding~\\
+~~~~~~~~~~~~raise~AttributeError('You~are~overriding~{\%}s!'~{\%}~name)~\\
+~~~~~~~~def~getter(self,~name=name):~\\
+~~~~~~~~~~~~return~getattr(self,~'{\_}'~+~name)~\\
+~~~~~~~~def~setter(self,~value,~name=name,~typecast=typecast):~\\
+~~~~~~~~~~~~setattr(self,~'{\_}'~+~name,~typecast(value))~\\
+~~~~~~~~setattr(cls,~name,~property(getter,~setter))~\\
+~~~~~~~~cls.fields.append(name)~\\
+~~~~~~~~cls.types.append(typecast)~\\
+~\\
+def~date(isodate):~{\#}~add~error~checking~if~you~like~\\
+~~~~"Convert~an~ISO~date~into~a~datetime.date~object"~\\
+~~~~return~datetime.date(*map(int,~isodate.split('-')))~\\
+~\\
+{\#}</{\_}main.py>
+}\end{quote}
+
+As an example of application of the above class initializer,
+I will define an \emph{Article} record class with fields \emph{title}, \emph{author}
+and \emph{date}:
+\begin{verbatim}>>> class Article(object):
+... # fields and types are dynamically set by the initializer
+... def_properties([('title', str), ('author', str), ('date', date)])
+... def __init__(self, values): # add error checking if you like
+... for field, cast, value in zip(self.fields, self.types, values):
+... setattr(self, '_' + field, cast(value))\end{verbatim}
+\begin{verbatim}>>> a=Article(['How to use class initializers', 'M. Simionato', '2006-07-10'])
+>>> a.title
+'How to use class initializers'
+>>> a.author
+'M. Simionato'
+>>> a.date
+datetime.date(2006, 7, 10)
+>>> a.date = '2006-07-11'
+>>> a.date
+datetime.date(2006, 7, 11)\end{verbatim}
+
+The point of using the class initializer is that the class is completely
+dynamic and it can be built at runtime with a schema that can be read
+from a configuration file or by introspecting a database table. You
+have the advantages of a custom metaclass without any of the disadvantages.
+
+It is also interesting to notice that this approach avoids inheritance
+completely, so if you have a pre-existing record class and you want
+to change its implementation to use this trick, it is enough to add
+\texttt{def{\_}properties}, you don't need any kind of (multiple)
+inheritance.
+
+
+%___________________________________________________________________________
+
+\hypertarget{references}{}
+\pdfbookmark[0]{References}{references}
+\section*{References}
+
+About metaclasses:
+\href{http://www-128.ibm.com/developerworks/linux/library/l-pymeta.html}{http://www-128.ibm.com/developerworks/linux/library/l-pymeta.html} and
+\href{http://www-128.ibm.com/developerworks/linux/library/l-pymeta2}{http://www-128.ibm.com/developerworks/linux/library/l-pymeta2}
+
+About using decorators instead of metaclasses:
+
+{\textless}David's last paper{\textgreater}
+
+The code from which everything was born:
+
+\href{http://svn.zope.org/Zope3/trunk/src/zope/interface/advice.py}{http://svn.zope.org/Zope3/trunk/src/zope/interface/advice.py}
+
+
+%___________________________________________________________________________
+
+\hypertarget{questions-and-answers}{}
+\pdfbookmark[0]{Questions and answers}{questions-and-answers}
+\section*{Questions and answers}
+\begin{description}
+%[visit_definition_list_item]
+\item[{Q}] %[visit_definition]
+
+Is there any specific licence for the code discussed in the paper?
+
+%[depart_definition]
+%[depart_definition_list_item]
+%[visit_definition_list_item]
+\item[{A}] %[visit_definition]
+
+No, you may assume the Public Domain or the Python licence, whatever
+you are happier with. If you are using my code, or
+code heavily derived from my own in your frameworks/applications I
+would appreciated to be notified, just to gratify my ego.
+
+%[depart_definition]
+%[depart_definition_list_item]
+%[visit_definition_list_item]
+\item[{Q}] %[visit_definition]
+
+How do I extract snippets of code from the paper?
+
+%[depart_definition]
+%[depart_definition_list_item]
+%[visit_definition_list_item]
+\item[{A}] %[visit_definition]
+
+Download \href{http://www.phyast.pitt.edu/~micheles/classinitializer.zip}{http://www.phyast.pitt.edu/{\textasciitilde}micheles/classinitializer.zip}
+which contains the source
+version of the paper (as well as the HTML and PDF versions)
+and a doctester utility. Run
+
+\texttt{{\$} python doctester.py classinitializer.txt}
+
+This will run many doctests and generate a script called \texttt{{\_}main.py}
+with the source code for \texttt{classinitializer} and \texttt{def{\_}properties}.
+
+%[depart_definition]
+%[depart_definition_list_item]
+%[visit_definition_list_item]
+\item[{Q}] %[visit_definition]
+
+The doctester is a really cool idea! Can I use it for my own projects?
+
+%[depart_definition]
+%[depart_definition_list_item]
+%[visit_definition_list_item]
+\item[{A}] %[visit_definition]
+
+Yes. See also
+\href{http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/410052}{http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/410052}
+
+%[depart_definition]
+%[depart_definition_list_item]
+\end{description}
+
+\end{document}
+