1ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot# This contains most of the executable examples from Guido's descr
2ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot# tutorial, once at
3ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot#
4ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot#     http://www.python.org/2.2/descrintro.html
5ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot#
6ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot# A few examples left implicit in the writeup were fleshed out, a few were
7ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot# skipped due to lack of interest (e.g., faking super() by hand isn't
8ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot# of much interest anymore), and a few were fiddled to make the output
9ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot# deterministic.
10ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
11ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robotfrom test.test_support import sortdict
12ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robotimport pprint
13ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
14ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robotclass defaultdict(dict):
15ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    def __init__(self, default=None):
16ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot        dict.__init__(self)
17ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot        self.default = default
18ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
19ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    def __getitem__(self, key):
20ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot        try:
21ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot            return dict.__getitem__(self, key)
22ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot        except KeyError:
23ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot            return self.default
24ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
25ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    def get(self, key, *args):
26ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot        if not args:
27ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot            args = (self.default,)
28ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot        return dict.get(self, key, *args)
29ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
30ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    def merge(self, other):
31ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot        for key in other:
32ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot            if key not in self:
33ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot                self[key] = other[key]
34ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
35ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robottest_1 = """
36ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
37ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team RobotHere's the new type at work:
38ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
39ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> print defaultdict               # show our type
40ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    <class 'test.test_descrtut.defaultdict'>
41ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> print type(defaultdict)         # its metatype
42ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    <type 'type'>
43ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> a = defaultdict(default=0.0)    # create an instance
44ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> print a                         # show the instance
45ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    {}
46ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> print type(a)                   # show its type
47ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    <class 'test.test_descrtut.defaultdict'>
48ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> print a.__class__               # show its class
49ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    <class 'test.test_descrtut.defaultdict'>
50ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> print type(a) is a.__class__    # its type is its class
51ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    True
52ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> a[1] = 3.25                     # modify the instance
53ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> print a                         # show the new value
54ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    {1: 3.25}
55ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> print a[1]                      # show the new item
56ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    3.25
57ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> print a[0]                      # a non-existent item
58ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    0.0
59ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> a.merge({1:100, 2:200})         # use a dict method
60ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> print sortdict(a)               # show the result
61ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    {1: 3.25, 2: 200}
62ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>>
63ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
64ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team RobotWe can also use the new type in contexts where classic only allows "real"
65ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robotdictionaries, such as the locals/globals dictionaries for the exec
66ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robotstatement or the built-in function eval():
67ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
68ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> def sorted(seq):
69ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    ...     seq.sort(key=str)
70ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    ...     return seq
71ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> print sorted(a.keys())
72ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    [1, 2]
73ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> exec "x = 3; print x" in a
74ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    3
75ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> print sorted(a.keys())
76ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    [1, 2, '__builtins__', 'x']
77ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> print a['x']
78ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    3
79ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>>
80ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
81ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team RobotNow I'll show that defaultdict instances have dynamic instance variables,
82ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robotjust like classic classes:
83ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
84ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> a.default = -1
85ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> print a["noway"]
86ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    -1
87ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> a.default = -1000
88ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> print a["noway"]
89ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    -1000
90ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> 'default' in dir(a)
91ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    True
92ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> a.x1 = 100
93ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> a.x2 = 200
94ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> print a.x1
95ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    100
96ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> d = dir(a)
97ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> 'default' in d and 'x1' in d and 'x2' in d
98ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    True
99ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> print sortdict(a.__dict__)
100ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    {'default': -1000, 'x1': 100, 'x2': 200}
101ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>>
102ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot"""
103ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
104ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robotclass defaultdict2(dict):
105ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    __slots__ = ['default']
106ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
107ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    def __init__(self, default=None):
108ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot        dict.__init__(self)
109ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot        self.default = default
110ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
111ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    def __getitem__(self, key):
112ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot        try:
113ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot            return dict.__getitem__(self, key)
114ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot        except KeyError:
115ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot            return self.default
116ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
117ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    def get(self, key, *args):
118ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot        if not args:
119ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot            args = (self.default,)
120ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot        return dict.get(self, key, *args)
121ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
122ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    def merge(self, other):
123ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot        for key in other:
124ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot            if key not in self:
125ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot                self[key] = other[key]
126ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
127ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robottest_2 = """
128ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
129ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team RobotThe __slots__ declaration takes a list of instance variables, and reserves
130ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robotspace for exactly these in the instance. When __slots__ is used, other
131ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robotinstance variables cannot be assigned to:
132ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
133ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> a = defaultdict2(default=0.0)
134ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> a[1]
135ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    0.0
136ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> a.default = -1
137ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> a[1]
138ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    -1
139ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> a.x1 = 1
140ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    Traceback (most recent call last):
141ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot      File "<stdin>", line 1, in ?
142ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    AttributeError: 'defaultdict2' object has no attribute 'x1'
143ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>>
144ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
145ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot"""
146ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
147ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robottest_3 = """
148ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
149ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team RobotIntrospecting instances of built-in types
150ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
151ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team RobotFor instance of built-in types, x.__class__ is now the same as type(x):
152ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
153ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> type([])
154ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    <type 'list'>
155ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> [].__class__
156ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    <type 'list'>
157ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> list
158ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    <type 'list'>
159ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> isinstance([], list)
160ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    True
161ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> isinstance([], dict)
162ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    False
163ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> isinstance([], object)
164ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    True
165ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>>
166ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
167ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team RobotUnder the new proposal, the __methods__ attribute no longer exists:
168ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
169ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> [].__methods__
170ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    Traceback (most recent call last):
171ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot      File "<stdin>", line 1, in ?
172ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    AttributeError: 'list' object has no attribute '__methods__'
173ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>>
174ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
175ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team RobotInstead, you can get the same information from the list type:
176ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
177ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> pprint.pprint(dir(list))    # like list.__dict__.keys(), but sorted
178ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    ['__add__',
179ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot     '__class__',
180ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot     '__contains__',
181ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot     '__delattr__',
182ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot     '__delitem__',
183ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot     '__delslice__',
184ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot     '__doc__',
185ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot     '__eq__',
186ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot     '__format__',
187ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot     '__ge__',
188ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot     '__getattribute__',
189ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot     '__getitem__',
190ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot     '__getslice__',
191ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot     '__gt__',
192ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot     '__hash__',
193ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot     '__iadd__',
194ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot     '__imul__',
195ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot     '__init__',
196ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot     '__iter__',
197ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot     '__le__',
198ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot     '__len__',
199ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot     '__lt__',
200ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot     '__mul__',
201ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot     '__ne__',
202ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot     '__new__',
203ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot     '__reduce__',
204ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot     '__reduce_ex__',
205ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot     '__repr__',
206ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot     '__reversed__',
207ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot     '__rmul__',
208ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot     '__setattr__',
209ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot     '__setitem__',
210ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot     '__setslice__',
211ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot     '__sizeof__',
212ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot     '__str__',
213ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot     '__subclasshook__',
214ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot     'append',
215ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot     'count',
216ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot     'extend',
217ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot     'index',
218ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot     'insert',
219ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot     'pop',
220ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot     'remove',
221ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot     'reverse',
222ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot     'sort']
223ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
224ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team RobotThe new introspection API gives more information than the old one:  in
225ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robotaddition to the regular methods, it also shows the methods that are
226ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robotnormally invoked through special notations, e.g. __iadd__ (+=), __len__
227ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot(len), __ne__ (!=). You can invoke any method from this list directly:
228ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
229ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> a = ['tic', 'tac']
230ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> list.__len__(a)          # same as len(a)
231ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    2
232ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> a.__len__()              # ditto
233ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    2
234ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> list.append(a, 'toe')    # same as a.append('toe')
235ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> a
236ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    ['tic', 'tac', 'toe']
237ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>>
238ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
239ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team RobotThis is just like it is for user-defined classes.
240ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot"""
241ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
242ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robottest_4 = """
243ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
244ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team RobotStatic methods and class methods
245ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
246ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team RobotThe new introspection API makes it possible to add static methods and class
247ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robotmethods. Static methods are easy to describe: they behave pretty much like
248ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robotstatic methods in C++ or Java. Here's an example:
249ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
250ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> class C:
251ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    ...
252ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    ...     @staticmethod
253ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    ...     def foo(x, y):
254ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    ...         print "staticmethod", x, y
255ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
256ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> C.foo(1, 2)
257ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    staticmethod 1 2
258ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> c = C()
259ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> c.foo(1, 2)
260ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    staticmethod 1 2
261ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
262ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team RobotClass methods use a similar pattern to declare methods that receive an
263ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robotimplicit first argument that is the *class* for which they are invoked.
264ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
265ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> class C:
266ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    ...     @classmethod
267ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    ...     def foo(cls, y):
268ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    ...         print "classmethod", cls, y
269ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
270ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> C.foo(1)
271ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    classmethod test.test_descrtut.C 1
272ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> c = C()
273ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> c.foo(1)
274ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    classmethod test.test_descrtut.C 1
275ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
276ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> class D(C):
277ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    ...     pass
278ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
279ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> D.foo(1)
280ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    classmethod test.test_descrtut.D 1
281ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> d = D()
282ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> d.foo(1)
283ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    classmethod test.test_descrtut.D 1
284ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
285ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team RobotThis prints "classmethod __main__.D 1" both times; in other words, the
286ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robotclass passed as the first argument of foo() is the class involved in the
287ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robotcall, not the class involved in the definition of foo().
288ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
289ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team RobotBut notice this:
290ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
291ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> class E(C):
292ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    ...     @classmethod
293ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    ...     def foo(cls, y): # override C.foo
294ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    ...         print "E.foo() called"
295ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    ...         C.foo(y)
296ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
297ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> E.foo(1)
298ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    E.foo() called
299ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    classmethod test.test_descrtut.C 1
300ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> e = E()
301ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> e.foo(1)
302ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    E.foo() called
303ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    classmethod test.test_descrtut.C 1
304ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
305ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team RobotIn this example, the call to C.foo() from E.foo() will see class C as its
306ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robotfirst argument, not class E. This is to be expected, since the call
307ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robotspecifies the class C. But it stresses the difference between these class
308ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robotmethods and methods defined in metaclasses (where an upcall to a metamethod
309ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robotwould pass the target class as an explicit first argument).
310ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot"""
311ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
312ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robottest_5 = """
313ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
314ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team RobotAttributes defined by get/set methods
315ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
316ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
317ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> class property(object):
318ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    ...
319ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    ...     def __init__(self, get, set=None):
320ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    ...         self.__get = get
321ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    ...         self.__set = set
322ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    ...
323ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    ...     def __get__(self, inst, type=None):
324ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    ...         return self.__get(inst)
325ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    ...
326ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    ...     def __set__(self, inst, value):
327ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    ...         if self.__set is None:
328ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    ...             raise AttributeError, "this attribute is read-only"
329ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    ...         return self.__set(inst, value)
330ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
331ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team RobotNow let's define a class with an attribute x defined by a pair of methods,
332ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robotgetx() and setx():
333ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
334ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> class C(object):
335ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    ...
336ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    ...     def __init__(self):
337ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    ...         self.__x = 0
338ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    ...
339ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    ...     def getx(self):
340ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    ...         return self.__x
341ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    ...
342ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    ...     def setx(self, x):
343ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    ...         if x < 0: x = 0
344ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    ...         self.__x = x
345ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    ...
346ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    ...     x = property(getx, setx)
347ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
348ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team RobotHere's a small demonstration:
349ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
350ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> a = C()
351ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> a.x = 10
352ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> print a.x
353ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    10
354ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> a.x = -10
355ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> print a.x
356ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    0
357ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>>
358ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
359ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team RobotHmm -- property is builtin now, so let's try it that way too.
360ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
361ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> del property  # unmask the builtin
362ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> property
363ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    <type 'property'>
364ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
365ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> class C(object):
366ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    ...     def __init__(self):
367ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    ...         self.__x = 0
368ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    ...     def getx(self):
369ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    ...         return self.__x
370ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    ...     def setx(self, x):
371ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    ...         if x < 0: x = 0
372ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    ...         self.__x = x
373ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    ...     x = property(getx, setx)
374ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
375ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
376ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> a = C()
377ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> a.x = 10
378ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> print a.x
379ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    10
380ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> a.x = -10
381ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>> print a.x
382ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    0
383ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    >>>
384ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot"""
385ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
386ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robottest_6 = """
387ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
388ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team RobotMethod resolution order
389ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
390ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team RobotThis example is implicit in the writeup.
391ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
392ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot>>> class A:    # classic class
393ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot...     def save(self):
394ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot...         print "called A.save()"
395ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot>>> class B(A):
396ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot...     pass
397ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot>>> class C(A):
398ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot...     def save(self):
399ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot...         print "called C.save()"
400ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot>>> class D(B, C):
401ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot...     pass
402ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
403ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot>>> D().save()
404ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robotcalled A.save()
405ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
406ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot>>> class A(object):  # new class
407ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot...     def save(self):
408ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot...         print "called A.save()"
409ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot>>> class B(A):
410ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot...     pass
411ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot>>> class C(A):
412ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot...     def save(self):
413ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot...         print "called C.save()"
414ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot>>> class D(B, C):
415ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot...     pass
416ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
417ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot>>> D().save()
418ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robotcalled C.save()
419ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot"""
420ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
421ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robotclass A(object):
422ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    def m(self):
423ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot        return "A"
424ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
425ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robotclass B(A):
426ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    def m(self):
427ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot        return "B" + super(B, self).m()
428ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
429ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robotclass C(A):
430ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    def m(self):
431ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot        return "C" + super(C, self).m()
432ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
433ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robotclass D(C, B):
434ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    def m(self):
435ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot        return "D" + super(D, self).m()
436ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
437ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
438ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robottest_7 = """
439ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
440ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team RobotCooperative methods and "super"
441ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
442ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot>>> print D().m() # "DCBA"
443ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team RobotDCBA
444ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot"""
445ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
446ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robottest_8 = """
447ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
448ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team RobotBackwards incompatibilities
449ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
450ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot>>> class A:
451ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot...     def foo(self):
452ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot...         print "called A.foo()"
453ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
454ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot>>> class B(A):
455ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot...     pass
456ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
457ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot>>> class C(A):
458ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot...     def foo(self):
459ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot...         B.foo(self)
460ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
461ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot>>> C().foo()
462ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team RobotTraceback (most recent call last):
463ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot ...
464ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team RobotTypeError: unbound method foo() must be called with B instance as first argument (got C instance instead)
465ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
466ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot>>> class C(A):
467ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot...     def foo(self):
468ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot...         A.foo(self)
469ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot>>> C().foo()
470ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robotcalled A.foo()
471ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot"""
472ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
473ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot__test__ = {"tut1": test_1,
474ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot            "tut2": test_2,
475ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot            "tut3": test_3,
476ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot            "tut4": test_4,
477ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot            "tut5": test_5,
478ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot            "tut6": test_6,
479ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot            "tut7": test_7,
480ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot            "tut8": test_8}
481ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
482ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot# Magic test name that regrtest.py invokes *after* importing this module.
483ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot# This worms around a bootstrap problem.
484ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot# Note that doctest and regrtest both look in sys.argv for a "-v" argument,
485ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot# so this works as expected in both ways of running regrtest.
486ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robotdef test_main(verbose=None):
487ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    # Obscure:  import this module as test.test_descrtut instead of as
488ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    # plain test_descrtut because the name of this module works its way
489ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    # into the doctest examples, and unless the full test.test_descrtut
490ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    # business is used the name can change depending on how the test is
491ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    # invoked.
492ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    from test import test_support, test_descrtut
493ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    test_support.run_doctest(test_descrtut, verbose)
494ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot
495ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot# This part isn't needed for regrtest, but for running the test directly.
496ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robotif __name__ == "__main__":
497ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot    test_main(1)
498