|
From: A.M. K. <aku...@us...> - 2001-10-23 20:26:19
|
Update of /cvsroot/py-howto/pyhowto
In directory usw-pr-cvs1:/tmp/cvs-serv32195
Modified Files:
python-22.tex
Log Message:
Fill out section on how to write a new-style class
Index: python-22.tex
===================================================================
RCS file: /cvsroot/py-howto/pyhowto/python-22.tex,v
retrieving revision 1.35
retrieving revision 1.36
diff -C2 -r1.35 -r1.36
*** python-22.tex 2001/10/22 15:32:05 1.35
--- python-22.tex 2001/10/23 20:26:16 1.36
***************
*** 1,2 ****
--- 1,3 ----
+
\documentclass{howto}
***************
*** 129,135 ****
intended to last forever; eventually old-style classes will be
dropped, possibly in Python 3.0.
! So how do you define a new-style class? XXX
! Subclass object -- subclass a built-in type.
--- 130,223 ----
intended to last forever; eventually old-style classes will be
dropped, possibly in Python 3.0.
+
+ So how do you define a new-style class? You do it by subclassing an
+ existing new-style class. Most of Python's built-in types, such as
+ integers, lists, dictionaries, and even files, are new-style classes
+ now. A new-style class named \class{object}, the base class for all
+ built-in types, has been also been added so if no built-in type is
+ suitable, you can just subclass \class{object}:
+
+ \begin{verbatim}
+ class C(object):
+ def __init__ (self):
+ ...
+ ...
+ \end{verbatim}
+
+ This means that \keyword{class} statements that don't have any base
+ classes are always classic classes in Python 2.2. There's actually a
+ way to make new-style classes without any base classes, by setting the
+ \member{__metaclass__} variable to XXX. (What do you set it to?)
+
+ The type objects for the built-in types are available as built-ins,
+ named using a clever trick. Python has always had built-in functions
+ named \function{int()}, \function{float()}, and \function{str()}. In
+ 2.2, they aren't functions any more, but type objects that behave as
+ factories when called.
+
+ \begin{verbatim}
+ >>> int
+ <type 'int'>
+ >>> int('123')
+ 123
+ \end{verbatim}
+
+ To make the set of types complete, new type objects such as
+ \function{dictionary} and \function{file} have been added.
+
+ Here's a more interesting example. The following class subclasses
+ Python's dictionary implementation in order to automatically fold all
+ dictionary keys to lowercase.
+
+ \begin{verbatim}
+ class LowerCaseDict(dictionary):
+ def _fold_key (self, key):
+ if not isinstance(key, str):
+ raise TypeError, "All keys must be strings"
+ return key.lower()
+
+ def __getitem__ (self, key):
+ key = self._fold_key(key)
+ return dictionary.__getitem__(self, key)
+
+ def __setitem__ (self, key, value):
+ key = self._fold_key(key)
+ dictionary.__setitem__(self, key, value)
+
+ def __delitem__ (self, key):
+ key = self._fold_key(key)
+ dictionary.__delitem__(self, key, value)
+ \end{verbatim}
+
+ Trying out this class, it works as you'd expect:
+
+ \begin{verbatim}
+ >>> d = LowerCaseDict()
+ >>> d['ABC'] = 1
+ >>> d['abc']
+ 1
+ \end{verbatim}
+
+ However, because it's a subclass of Python's dictionary type,
+ instances of \class{LowerCaseDict} can be used in most places where a
+ regular dictionary is required.
+
+ \begin{verbatim}
+ >>> d = LowerCaseDict()
+ >>> exec 'Name = 1' in d
+ >>> print d.items()
+ XXX
+ >>> exec 'nAmE = name + 1' in d
+ >>> print d.items()
+ XXX
+ \end{verbatim}
! And now you can have Python with case-insensitive variable names! One
! of the nice things about Python 2.2 is that it makes Python flexible
! enough to solve many other past problems without hacking Python's C
! code. If you want a case-insensitive Python environment, using a
! case-folding dictionary and writing a case-insensitive tokenizer using
! the compiler package (now automatically installed in 2.2) will make it
! a straightforward.
***************
*** 234,245 ****
ignore the implementation details.
! \subsection{Inheritance Lookup: The Diamond Rule}
! XXX
\subsection{Attribute Access}
XXX __getattribute__, __getattr__
\subsection{Related Links}
\ref{sect-rellinks}
--- 322,385 ----
ignore the implementation details.
! \subsection{Multiple Inheritance: The Diamond Rule}
! Multiple inheritance has also been made more useful through changing
! the rules under which names are resolved. Consider this set of classes
! (diagram taken from \pep{253} by Guido van Rossum):
!
! \begin{verbatim}
! class A:
! ^ ^ def save(self): ...
! / \
! / \
! / \
! / \
! class B class C:
! ^ ^ def save(self): ...
! \ /
! \ /
! \ /
! \ /
! class D
! \end{verbatim}
+ The lookup rule for classic classes is simple but not very smart; the
+ base classes are searched depth-first, going from left to right. A
+ reference to \method{D.save} will search the classes \class{D},
+ \class{B}, and then \class{A}, where \method{save()} would be found
+ and returned. \method{C.save()} would never be found at all. This is
+ bad, because if \class{C}'s \method{save()} method is saving some
+ internal state specific to \class{C}, not calling it will result in
+ that state never getting saved.
+
+ New-style classes follow a different algorithm that's a bit more
+ complicated to explain, but does the right thing in this situation.
+
+ \begin{enumerate}
+
+ \item List all the base classes, following the classic lookup rule and
+ include a class multiple times if it's visited repeatedly. In the
+ above example, the list of visited classes is [\class{D}, \class{B},
+ \class{A}, \class{C}, class{A}].
+
+ \item Scan the list for duplicated classes. If any are found, remove
+ all but one occurrence, leaving the \emph{last} one in the list. In
+ the above example, the list becomes [\class{D}, \class{B}, \class{C},
+ class{A}] after dropping duplicates.
+
+ \end{enumerate}
+
+ Following this rule, referring to \method{D.save()} will return
+ \method{C.save()}, which is the behaviour we're after. This lookup
+ rule is the same as the one followed by XXX Common Lisp?.
+
+
\subsection{Attribute Access}
XXX __getattribute__, __getattr__
+ XXX properties, slots
+
+
\subsection{Related Links}
\ref{sect-rellinks}
***************
*** 265,268 ****
--- 405,409 ----
Finally, there's the ultimate authority: the source code.
+ typeobject.c, others?
% XXX point people at the right files
***************
*** 350,354 ****
>>> a,b,c
(1, 2, 3)
- >>>
\end{verbatim}
--- 491,494 ----
***************
*** 374,378 ****
Dec 12
Oct 10
- >>>
\end{verbatim}
--- 514,517 ----
***************
*** 472,476 ****
File "<stdin>", line 2, in generate_ints
StopIteration
- >>>
\end{verbatim}
--- 611,614 ----
|