From: A.M. K. <aku...@us...> - 2001-10-26 20:07:05
|
Update of /cvsroot/py-howto/pyhowto In directory usw-pr-cvs1:/tmp/cvs-serv21846 Modified Files: python-22.tex Log Message: Finish off the type/class section; I don't think there's much else to be covered in an overview article like this. Index: python-22.tex =================================================================== RCS file: /cvsroot/py-howto/pyhowto/python-22.tex,v retrieving revision 1.36 retrieving revision 1.37 diff -C2 -r1.36 -r1.37 *** python-22.tex 2001/10/23 20:26:16 1.36 --- python-22.tex 2001/10/26 20:07:03 1.37 *************** *** 1,3 **** - \documentclass{howto} --- 1,2 ---- *************** *** 15,19 **** {\large This document is a draft, and is subject to change until the final version of Python 2.2 is released. Currently it's up to date ! for Python 2.2 alpha 4. Please send any comments, bug reports, or questions, no matter how minor, to \email{aku...@me...}. } --- 14,18 ---- {\large This document is a draft, and is subject to change until the final version of Python 2.2 is released. Currently it's up to date ! for Python 2.2 beta 1. Please send any comments, bug reports, or questions, no matter how minor, to \email{aku...@me...}. } *************** *** 148,152 **** 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, --- 147,152 ---- 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?), but ! it's easier to just subclass \keyword{object}. The type objects for the built-in types are available as built-ins, *************** *** 164,225 **** 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. - \subsection{Descriptors} --- 164,186 ---- 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, adding a \method{lock()} method to file ! objects: ! ! \begin{verbatim} ! class LockableFile(file): ! def lock (self, operation, length=0, start=0, whence=0): ! import fcntl ! return fcntl.lockf(self.fileno(), operation, ! length, start, whence) ! \end{verbatim} ! ! The now-obsolete \module{posixfile} module contained a class that ! emulated all of a file object's methods and also added a ! \method{lock()} method, but this class couldn't be passed to internal ! functions that expected a built-in file, something which is possible ! with our new \class{LockableFile}. \subsection{Descriptors} *************** *** 372,385 **** 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} --- 333,432 ---- 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 Common Lisp. \subsection{Attribute Access} ! A fair number of sophisticated Python classes define hooks for ! attribute access using \method{__getattr__}; most commonly this is ! done for convenience, to make code more readable by automatically ! mapping an attribute access such as \code{obj.parent} into a method ! call such as \code{obj.get_parent()}. Python 2.2 adds some new ways ! of controlling attribute access. ! ! First, \method{__getattr__(\var{attr_name})} is still supported by ! new-style classes, and nothing about it has changed. As before, it ! will be called when an attempt is made to access \code{obj.foo} and no ! attribute named \samp{foo} is found in the instance's dictionary. ! ! New-style classes also support a new method, ! \method{__getattribute__(\var{attr_name})}. The difference between ! the two methods is that \method{__getattribute__} is \emph{always} ! called whenever any attribute is accessed, while the old ! \method{__getattr__} is only called if \samp{foo} isn't found in the ! instance's dictionary. ! ! However, Python 2.2's support for \dfn{properties} will often be a ! simpler way to trap attribute references. Writing a ! \method{__getattr__} method is complicated because to avoid recursion ! you can't use regular attribute accesses inside them, and instead have ! to mess around with the contents of \member{__dict__}. ! \method{__getattr__} methods also end up being called by Python when ! it checks for other methods such as \method{__repr__} or ! \method{__coerce__}, and so have to be written with this in mind. ! Finally, calling a function on every attribute access results in a ! sizable performance loss. ! ! \class{property} is a new built-in type that packages up three ! functions that get, set, or delete an attribute, and a docstring. For ! example, if you want to define a \member{size} attribute that's ! computed, but also settable, you could write: ! \begin{verbatim} ! class C: ! def get_size (self): ! result = ... computation ... ! return result ! def set_size (self, size): ! ... compute something based on the size ! and set internal state appropriately ... ! ! # Define a property. The 'delete this attribute' ! # method is defined as None, so the attribute ! # can't be deleted. ! size = property(get_size, set_size, ! None, ! "Storage size of this instance") ! \end{verbatim} ! ! That is certainly clearer and easier to write than a pair of ! \method{__getattr__}/\method{__setattr__} methods that check for the ! \member{size} attribute and handle it specially, while retrieving all ! other attributes from the instance's \member{__dict__}. Accesses to ! \member{size} are also the only ones which have to perform the work of ! calling a function, letting references to other attributes run at ! their usual speed. ! ! Finally, it's possible to constrain the list of attributes that can be ! referenced on an object using the new \member{__slots__} attribute. ! Python objects are usually very dynamic; at any time it's possible to ! define a new attribute on an instance by just doing ! \code{obj.new_attr=1}. This is flexible and convenient, but this ! flexibility can also lead to bugs, as when you meant to write ! \code{obj.template = 'a'} but make a typo and wrote ! \code{obj.templtae} by accident. ! ! A new-style class can define a class variable named \member{__slots__} ! to constrain the list of legal attribute names. An example will make ! this clear: + \begin{verbatim} + >>> class C(object): + ... __slots__ = ['template', 'name'] + ... + >>> obj = C() + >>> print obj.template + None + >>> obj.template = 'Test' ; obj.name = 'abc' + >>> print obj.template + Test + >>> obj.templtae + Traceback (most recent call last): + File "<stdin>", line 1, in ? + AttributeError: 'C' object has no attribute 'templtae' + \end{verbatim} + + \subsection{Related Links} \ref{sect-rellinks} *************** *** 390,396 **** more complete picture? ! \url{http://www.python.org/2.2/descrintro.html} is a tutorial introduction to the descriptor features, written by Guido van Rossum. ! % XXX read it and comment on it Next, there are two relevant PEPs, \pep{252} and \pep{253}. \pep{252} --- 437,445 ---- more complete picture? ! \url{http://www.python.org/2.2/descrintro.html} is a lengthy tutorial introduction to the descriptor features, written by Guido van Rossum. ! If my description has whetted your appetite, go read this tutorial ! next, because it goes into much more detail about the new features ! while still remaining quite easy to read. Next, there are two relevant PEPs, \pep{252} and \pep{253}. \pep{252} *************** *** 398,410 **** descriptor API. \pep{253} is titled "Subtyping Built-in Types", and describes the changes to type objects that make it possible to subtype ! built-in objects. This is the more complicated PEP of the two, and at ! a few points the necessary explanations of types and meta-types may ! cause your head to explode. Both PEPs were written and implemented by ! Guido van Rossum, with substantial assistance from the rest of the ! Zope Corp. team. ! ! Finally, there's the ultimate authority: the source code. ! typeobject.c, others? ! % XXX point people at the right files --- 447,460 ---- descriptor API. \pep{253} is titled "Subtyping Built-in Types", and describes the changes to type objects that make it possible to subtype ! built-in objects. \pep{253} is the more complicated PEP of the two, ! and at a few points the necessary explanations of types and meta-types ! may cause your head to explode. Both PEPs were written and ! implemented by Guido van Rossum, with substantial assistance from the ! rest of the Zope Corp. team. ! ! Finally, there's the ultimate authority: the source code. Most of the ! machinery for the type handling is in \file{Objects/typeobject.c}, but ! you should only resort to it after all other avenues have been ! exhausted (including posting a question to python-list or python-dev.) *************** *** 1097,1100 **** --- 1147,1152 ---- affect you very much. + % XXX PyArg_UnpackTuple() + \begin{itemize} *************** *** 1296,1304 **** The author would like to thank the following people for offering ! suggestions and corrections to various drafts of this article: Fred ! Bremmer, Keith Briggs, Andrew Dalke, Fred~L. Drake, Jr., Carel ! Fellinger, Mark Hammond, Stephen Hansen, Jack Jansen, Marc-Andr\'e ! Lemburg, Fredrik Lundh, Tim Peters, Neil Schemenauer, Guido van ! Rossum. \end{document} --- 1348,1356 ---- The author would like to thank the following people for offering ! suggestions, corrections and assistance with various drafts of this ! article: Fred Bremmer, Keith Briggs, Andrew Dalke, Fred~L. Drake, Jr., ! Carel Fellinger, Mark Hammond, Stephen Hansen, Jack Jansen, ! Marc-Andr\'e Lemburg, Fredrik Lundh, Tim Peters, Tom Reinhardt, Neil ! Schemenauer, Guido van Rossum. \end{document} |