diff --git a/advanced-classes.html b/advanced-classes.html new file mode 100644 index 0000000..b078fe8 --- /dev/null +++ b/advanced-classes.html @@ -0,0 +1,98 @@ + + + +Advanced Classes - Dive into Python 3 + + + + + +
  
+

You are here: Home Dive Into Python 3 +

Difficulty level: ♦♦♦♦♢ +

Advanced Classes

+
+

FIXME
— FIXME +

+

  +

Diving In

+

FIXME + +

[download ordereddict.py] +

import collections
+import itertools
+ 
+class OrderedDict(dict, collections.MutableMapping):
+
+    def __init__(self, *args, **kwds):
+        if len(args) > 1:
+            raise TypeError('expected at most 1 arguments')
+        if not hasattr(self, '_keys'):
+            self._keys = []
+        self.update(*args, **kwds)
+
+    def clear(self):
+        del self._keys[:]
+        dict.clear(self)
+
+    def __setitem__(self, key, value):
+        if key not in self:
+            self._keys.append(key)
+        dict.__setitem__(self, key, value)
+
+    def __delitem__(self, key):
+        dict.__delitem__(self, key)
+        self._keys.remove(key)
+
+    def __iter__(self):
+        return iter(self._keys)
+
+    def __reversed__(self):
+        return reversed(self._keys)
+
+    def popitem(self):
+        if not self:
+            raise KeyError('dictionary is empty')
+        key = self._keys.pop()
+        value = dict.pop(self, key)
+        return key, value
+
+    def __reduce__(self):
+        items = [[k, self[k]] for k in self]
+        inst_dict = vars(self).copy()
+        inst_dict.pop('_keys', None)
+        return (self.__class__, (items,), inst_dict)
+
+    setdefault = MutableMapping.setdefault
+    update = MutableMapping.update
+    pop = MutableMapping.pop
+    keys = MutableMapping.keys
+    values = MutableMapping.values
+    items = MutableMapping.items
+
+    def __repr__(self):
+        if not self:
+            return '%s()' % (self.__class__.__name__,)
+        return '%s(%r)' % (self.__class__.__name__, list(self.items()))
+
+    def copy(self):
+        return self.__class__(self)
+
+    @classmethod
+    def fromkeys(cls, iterable, value=None):
+        d = cls()
+        for key in iterable:
+            d[key] = value
+        return d
+
+    def __eq__(self, other):
+        if isinstance(other, OrderedDict):
+            return all(p==q for p, q in itertools.zip_longest(self.items(), other.items()))
+        return dict.__eq__(self, other)
+ +

© 2001–9 Mark Pilgrim + + diff --git a/index.html b/index.html index 42dd359..0de1157 100644 --- a/index.html +++ b/index.html @@ -6,8 +6,9 @@ @@ -33,17 +34,18 @@ h1:before{content:""}

  • Unit Testing
  • Test-first programming
  • Refactoring +
  • Advanced Classes
  • Files
  • HTML processing
  • XML processing
  • Web services -
  • Metaclasses
  • Performance tuning
  • Packaging Python libraries
  • Creating graphics with the Python Imaging Library
  • Where to go from here
  • Case Study: Porting chardet to Python 3 -
  • Porting Code to Python 3 with 2to3 +
  • Porting Code to Python 3 with 2to3 +
  • Special Method Names

    There is a changelog, a feed, and discussion on Reddit. During development, you can download the book by cloning the Mercurial repository: diff --git a/porting-code-to-python-3-with-2to3.html b/porting-code-to-python-3-with-2to3.html index 1cf9369..42fe31e 100644 --- a/porting-code-to-python-3-with-2to3.html +++ b/porting-code-to-python-3-with-2to3.html @@ -31,11 +31,9 @@ td pre{padding:0;border:0}

    print statement

    In Python 2, print was a statement. Whatever you wanted to print simply followed the print keyword. In Python 3, print() is a function — whatever you want to print is passed to print() like any other function. - -
    Notes -Python 2 -Python 3 - +
    Notes +Python 2 +Python 3
    print print() @@ -65,7 +63,6 @@ td pre{padding:0;border:0}
    Notes Python 2 Python 3 -
    u"PapayaWhip" "PapayaWhip" @@ -83,7 +80,6 @@ td pre{padding:0;border:0}
    Notes Python 2 Python 3 -
    unicode(anything) str(anything) @@ -95,7 +91,6 @@ td pre{padding:0;border:0}
    Notes Python 2 Python 3 -
    x = 1000000000000L x = 1000000000000 @@ -125,7 +120,6 @@ td pre{padding:0;border:0}
    Notes Python 2 Python 3 -
    if x <> y: if x != y: @@ -143,7 +137,6 @@ td pre{padding:0;border:0}
    Notes Python 2 Python 3 -
    a_dictionary.has_key("PapayaWhip") "PapayaWhip" in a_dictionary @@ -173,7 +166,6 @@ td pre{padding:0;border:0}
    Notes Python 2 Python 3 -
    a_dictionary.keys() list(a_dictionary.keys()) @@ -205,7 +197,6 @@ td pre{padding:0;border:0}
    Notes Python 2 Python 3 -
    import httplib import http.client @@ -233,7 +224,6 @@ import CGIHttpServer
    Notes Python 2 Python 3 -
    import urllib import urllib.request, urllib.parse, urllib.error @@ -271,7 +261,6 @@ from urllib.error import HTTPError
    Notes Python 2 Python 3 -
    import dbm import dbm.ndbm @@ -295,7 +284,6 @@ import whichdb
    Notes Python 2 Python 3 -
    import xmlrpclib import xmlrpc.client @@ -309,7 +297,6 @@ import SimpleXMLRPCServer
    Notes Python 2 Python 3 -
    try:
         import cStringIO as StringIO
    @@ -372,7 +359,6 @@ except ImportError:
     
    Notes Python 2 Python 3 -
    import constants from . import constants @@ -390,7 +376,6 @@ except ImportError:
    Notes Python 2 Python 3 -
    anIterator.next() next(anIterator) @@ -430,7 +415,6 @@ for an_iterator in a_sequence_of_iterators:
    Notes Python 2 Python 3 -
    filter(a_function, a_sequence) list(filter(a_function, a_sequence)) @@ -460,7 +444,6 @@ for an_iterator in a_sequence_of_iterators:
    Notes Python 2 Python 3 -
    map(a_function, 'PapayaWhip') list(map(a_function, 'PapayaWhip')) @@ -490,7 +473,6 @@ for an_iterator in a_sequence_of_iterators:
    Notes Python 2 Python 3 -
    reduce(a, b, c)
    from functtools import reduce
    @@ -505,7 +487,6 @@ reduce(a, b, c)
    Notes Python 2 Python 3 -
    apply(a_function, a_list_of_args) a_function(*a_list_of_args) @@ -531,7 +512,6 @@ reduce(a, b, c)
    Notes Python 2 Python 3 -
    intern(aString) sys.intern(aString) @@ -542,7 +522,6 @@ reduce(a, b, c)
    Notes Python 2 Python 3 -
    exec codeString exec(codeString) @@ -564,7 +543,6 @@ reduce(a, b, c)
    Notes Python 2 Python 3 -
    execfile("a_filename") exec(compile(open("a_filename").read(), "a_filename", "exec")) @@ -578,7 +556,6 @@ reduce(a, b, c)
    Notes Python 2 Python 3 -
    `x` repr(x) @@ -596,7 +573,6 @@ reduce(a, b, c)
    Notes Python 2 Python 3 -
    try:
         import mymodule
    @@ -643,7 +619,6 @@ except:
     
    Notes Python 2 Python 3 -
    raise MyException unchanged @@ -669,7 +644,6 @@ except:
    Notes Python 2 Python 3 -
    a_generator.throw(MyException) no change @@ -691,7 +665,6 @@ except:
    Notes Python 2 Python 3 -
    xrange(10) range(10) @@ -721,7 +694,6 @@ except:
    Notes Python 2 Python 3 -
    raw_input() input() @@ -743,7 +715,6 @@ except:
    Notes Python 2 Python 3 -
    a_function.func_name a_function.__name__ @@ -781,7 +752,6 @@ except:
    Notes Python 2 Python 3 -
    for line in a_file.xreadlines(): for line in a_file: @@ -800,7 +770,6 @@ except:
    Notes Python 2 Python 3 -
    lambda (x,): x + f(x) lambda x1: x1[0] + f(x1[0]) @@ -826,7 +795,6 @@ except:
    Notes Python 2 Python 3 -
    aClassInstance.aClassMethod.im_func aClassInstance.aClassMethod.__func__ @@ -843,7 +811,6 @@ except:
    Notes Python 2 Python 3 -
    class A:
         def __nonzero__(self):
    @@ -867,7 +834,6 @@ except:
     
    Notes Python 2 Python 3 -
    x = 0755 x = 0o755 @@ -878,7 +844,6 @@ except:
    Notes Python 2 Python 3 -
    from sys import maxint from sys import maxsize @@ -896,7 +861,6 @@ except:
    Notes Python 2 Python 3 -
    callable(anything) hasattr(anything, "__call__") @@ -907,7 +871,6 @@ except:
    Notes Python 2 Python 3 -
    zip(a, b, c) list(zip(a, b, c)) @@ -925,7 +888,6 @@ except:
    Notes Python 2 Python 3 -
    x = StandardError() x = Exception() @@ -939,7 +901,6 @@ except:
    Notes Python 2 Python 3 -
    types.StringType bytes @@ -965,7 +926,6 @@ except:
    Notes Python 2 Python 3 -
    isinstance(x, (int, float, int)) isinstance(x, (int, float)) @@ -979,7 +939,6 @@ except:
    Notes Python 2 Python 3 -
    isinstance(x, basestring) isinstance(x, str) @@ -990,7 +949,6 @@ except:
    Notes Python 2 Python 3 -
    itertools.izip(a, b) zip(a, b) @@ -1016,7 +974,6 @@ except:
    Notes Python 2 Python 3 -
    sys.exc_type sys.exc_info()[0] @@ -1033,7 +990,6 @@ except:
    Notes Python 2 Python 3 -
    [i for i in 1, 2] [i for i in (1, 2)] @@ -1044,7 +1000,6 @@ except:
    Notes Python 2 Python 3 -
    os.getcwdu() os.getcwd() @@ -1055,7 +1010,6 @@ except:
    Notes Python 2 Python 3 -
    class C(metaclass=PapayaMeta):
         pass
    @@ -1158,7 +1112,7 @@ do_stuff(a_list) do_stuff(a_list)

    FIXME: once the rest of the book is written, this appendix should contain copious links back to any chapter or section that touches on these features. -

    © 2001–9 Mark Pilgrim diff --git a/special-method-names.html b/special-method-names.html index 55dba50..31bb0fb 100644 --- a/special-method-names.html +++ b/special-method-names.html @@ -5,105 +5,44 @@

      

    You are here: Home Dive Into Python 3 -

    Difficulty level: ♦♦♦♦♢ +

    Difficulty level: ♦♦♦♦♦

    Special Method Names

    FIXME
    — FIXME

      -

    Diving In

    +

    Diving in

    FIXME -

    [download ordereddict.py] -

    import collections
    -import itertools
    - 
    -class OrderedDict(dict, collections.MutableMapping):
    -
    -    def __init__(self, *args, **kwds):
    -        if len(args) > 1:
    -            raise TypeError('expected at most 1 arguments')
    -        if not hasattr(self, '_keys'):
    -            self._keys = []
    -        self.update(*args, **kwds)
    -
    -    def clear(self):
    -        del self._keys[:]
    -        dict.clear(self)
    -
    -    def __setitem__(self, key, value):
    -        if key not in self:
    -            self._keys.append(key)
    -        dict.__setitem__(self, key, value)
    -
    -    def __delitem__(self, key):
    -        dict.__delitem__(self, key)
    -        self._keys.remove(key)
    -
    -    def __iter__(self):
    -        return iter(self._keys)
    -
    -    def __reversed__(self):
    -        return reversed(self._keys)
    -
    -    def popitem(self):
    -        if not self:
    -            raise KeyError('dictionary is empty')
    -        key = self._keys.pop()
    -        value = dict.pop(self, key)
    -        return key, value
    -
    -    def __reduce__(self):
    -        items = [[k, self[k]] for k in self]
    -        inst_dict = vars(self).copy()
    -        inst_dict.pop('_keys', None)
    -        return (self.__class__, (items,), inst_dict)
    -
    -    setdefault = MutableMapping.setdefault
    -    update = MutableMapping.update
    -    pop = MutableMapping.pop
    -    keys = MutableMapping.keys
    -    values = MutableMapping.values
    -    items = MutableMapping.items
    -
    -    def __repr__(self):
    -        if not self:
    -            return '%s()' % (self.__class__.__name__,)
    -        return '%s(%r)' % (self.__class__.__name__, list(self.items()))
    -
    -    def copy(self):
    -        return self.__class__(self)
    -
    -    @classmethod
    -    def fromkeys(cls, iterable, value=None):
    -        d = cls()
    -        for key in iterable:
    -            d[key] = value
    -        return d
    -
    -    def __eq__(self, other):
    -        if isinstance(other, OrderedDict):
    -            return all(p==q for p, q in itertools.zip_longest(self.items(), other.items()))
    -        return dict.__eq__(self, other)
    - - -Acts like a dictionary: +

    Classes That Act Like Dictionaries

    +
     __getitem__
     __setitem__ - covered in ordereddict.py
     __delitem__ - covered in ordereddict.py
     __missing__ (*)
    +
    -Acts like an iterator: +

    Classes That Act Like Iterators

    + +
     __iter__ (*) - covered in iterators.html
     __next__ (*) - covered in iterators.html
    +__reversed__ - covered in ordereddict.py
    +
    -Acts like a number: +

    Classes That Act Like Numbers

    +

    FIXME binary operator intro + + +
    Notes +You Want… +So You Write… +And Python Calls… +
    +addition +x + y +x.__add__(y) +
    +subtraction +x - y +x.__sub__(y) +
    +multiplication +x * y +x.__mul__(y) +
    +division +x / y +x.__truediv__(y) +
    +floor division +x // y +x.__floordiv__(y) +
    +modulo (remainder) +x % y +x.__mod__(y) +
    +floor division & modulo +divmod(x, y) +x.__divmod__(y) +
    +raise to power +x ** y +x.__pow__(y) +
    +left bit-shift +x << y +x.__lshift__(y) +
    +right bit-shift +x >> y +x.__rshift__(y) +
    +bitwise and +x & y +x.__and__(y) +
    +bitwise xor +x ^ y +x.__xor__(y) +
    +bitwise or +x | y +x.__or__(y) +
    + + + +

    FIXME explain circumstances under which reflected methods will be called. + + +
    Notes +You Want… +So You Write… +And Python Calls… +
    +addition +x + y +y.__radd__(x) +
    +subtraction +x - y +y.__rsub__(x) +
    +multiplication +x * y +y.__rmul__(x) +
    +division +x / y +y.__rtruediv__(x) +
    +floor division +x // y +y.__rfloordiv__(x) +
    +modulo (remainder) +x % y +y.__rmod__(x) +
    +floor division & modulo +divmod(x, y) +y.__rdivmod__(x) +
    +raise to power +x ** y +y.__rpow__(x) +
    +left bit-shift +x << y +y.__rlshift__(x) +
    +right bit-shift +x >> y +y.__rrshift__(x) +
    +bitwise and +x & y +y.__rand__(x) +
    +bitwise xor +x ^ y +y.__rxor__(x) +
    +bitwise or +x | y +y.__ror__(x) +
    + + + +

    FIXME explain in-place augmented assignments + + +
    Notes +You Want… +So You Write… +And Python Calls… +
    +in-place addition +x += y +x.__iadd__(y) +
    +in-place subtraction +x -= y +x.__isub__(y) +
    +in-place multiplication +x *= y +x.__imul__(y) +
    +in-place division +x /= y +x.__itruediv__(y) +
    +in-place floor division +x //= y +x.__ifloordiv__(y) +
    +in-place modulo +x %= y +x.__imod__(y) +
    +in-place raise to power +x **= y +x.__ipow__(y) +
    +in-place left bit-shift +x <<= y +x.__ilshift__(y) +
    +in-place right bit-shift +x >>= y +x.__irshift__(y) +
    +in-place bitwise and +x &= y +x.__iand__(y) +
    +in-place bitwise xor +x ^= y +x.__ixor__(y) +
    +in-place bitwise or +x |= y +x.__ior__(y) +
    + + + +

    FIXME unary operator intro + + +
    Notes +You Want… +So You Write… +And Python Calls… +
    +negative number +-x +x.__neg__() +
    +positive number ++x +x.__pos__() +
    +absolute value +abs(x) +x.__abs__() +
    +inverse +~x +x.__invert__() +
    +complex number +complex(x) +x.__complex__() +
    +integer +int(x) +x.__int__() +
    +floating point number +float(x) +x.__float__() +
    +number rounded to nearest integer +round(x) +x.__round__() +
    +number rounded to nearest n digits +round(x, n) +x.__round__(n) +
    +smallest integer >= x +math.ceil(x) +x.__ceil__() +
    +largest integer <= x +math.floor(x) +x.__floor__() +
    +truncate x to nearest integer toward 0 +math.trunc(x) +x.__trunc__() +
    +??? +??? +x.__index__() +
    + + -Support for pickling, see http://docs.python.org/3.0/library/pickle.html: +

    Support For Pickling

    + +
    +see http://docs.python.org/3.0/library/pickle.html:
     
     __copy__ (*) - covered in fractions.py
     __deepcopy__ (*) - covered in fractions.py
    @@ -207,9 +432,18 @@ __getstate__ (*)
     __setstate__ (*)
     __reduce__ (*) - covered in ordereddict.py, fractions.py
     __reduce_ex__ (*)
    +
    -Really weird stuff: +

    Classes That Can Be Used in a with Block

    +
    +__enter__ see http://docs.python.org/3.0/library/stdtypes.html#typecontextmanager
    +__exit__
    +
    + +

    Really Esoteric Stuff

    + +
     __new__ - covered in fractions.py
     __del__
     __slots__
    @@ -217,15 +451,12 @@ __hash__ - covered in fractions.py
     __get__
     __set__
     __delete__
    -__enter__ see http://docs.python.org/3.0/library/stdtypes.html#typecontextmanager
    -__exit__
     __subclasshook__ (*) see http://docs.python.org/3.0/library/abc.html
     __instancecheck__ (*) see http://www.ibm.com/developerworks/linux/library/l-python3-2/
     __subclasscheck__ (*)
    +
    ---> - -

    © 2001–9 Mark Pilgrim diff --git a/table-of-contents.html b/table-of-contents.html index e2af73a..afb6b0e 100644 --- a/table-of-contents.html +++ b/table-of-contents.html @@ -177,6 +177,10 @@ ul li ol{margin:0;padding:0 0 0 2.5em}

  • Postscript
  • Summary +
  • Advanced Classes +
      +
    1. Diving in +
  • Files
    1. File objects @@ -229,10 +233,6 @@ ul li ol{margin:0;padding:0 0 0 2.5em}
    2. Putting it all together
    3. Summary
    -
  • Metaclasses -
      -
    1. ...once I figure out WTF metaclasses are... -
  • Performance tuning
    1. Diving in @@ -362,6 +362,21 @@ ul li ol{margin:0;padding:0 0 0 2.5em}
    2. Common idioms
    +
  • Appendix B. Special Method Names +
      +
    1. Diving in +
    2. Basics +
    3. Rich Comparisons +
    4. Custom Attributes +
    5. Classes That Act Like Functions +
    6. Classes That Act Like Sequences +
    7. Classes That Act Like Dictionaries +
    8. Classes That Act Like Iterators +
    9. Classes That Act Like Numbers +
    10. Support For Pickling +
    11. Classes That Can Be Used in a with Block +
    12. Really Esoteric Stuff +

    Orphans (not sure where these belong yet):