blob: 3351b67ecb7f6895881604b9466a95cb341e4818 [file] [log] [blame]
Tim Peters95c99e52001-09-03 01:24:30 +00001# This contains most of the executable examples from Guido's descr
2# tutorial, once at
3#
4# http://www.python.org/2.2/descrintro.html
5#
6# A few examples left implicit in the writeup were fleshed out, a few were
7# skipped due to lack of interest (e.g., faking super() by hand isn't
8# of much interest anymore), and a few were fiddled to make the output
9# deterministic.
10
Barry Warsaw04f357c2002-07-23 19:04:11 +000011from test.test_support import sortdict
Tim Peters95c99e52001-09-03 01:24:30 +000012import pprint
13
Tim Petersa427a2b2001-10-29 22:25:45 +000014class defaultdict(dict):
Tim Peters95c99e52001-09-03 01:24:30 +000015 def __init__(self, default=None):
Tim Petersa427a2b2001-10-29 22:25:45 +000016 dict.__init__(self)
Tim Peters95c99e52001-09-03 01:24:30 +000017 self.default = default
18
19 def __getitem__(self, key):
20 try:
Tim Petersa427a2b2001-10-29 22:25:45 +000021 return dict.__getitem__(self, key)
Tim Peters95c99e52001-09-03 01:24:30 +000022 except KeyError:
23 return self.default
24
25 def get(self, key, *args):
26 if not args:
27 args = (self.default,)
Tim Petersa427a2b2001-10-29 22:25:45 +000028 return dict.get(self, key, *args)
Tim Peters95c99e52001-09-03 01:24:30 +000029
30 def merge(self, other):
31 for key in other:
32 if key not in self:
33 self[key] = other[key]
34
35test_1 = """
36
37Here's the new type at work:
38
Guido van Rossum7131f842007-02-09 20:13:25 +000039 >>> print(defaultdict) # show our type
Guido van Rossuma4cb7882001-09-25 03:56:29 +000040 <class 'test.test_descrtut.defaultdict'>
Guido van Rossum7131f842007-02-09 20:13:25 +000041 >>> print(type(defaultdict)) # its metatype
Tim Peters95c99e52001-09-03 01:24:30 +000042 <type 'type'>
43 >>> a = defaultdict(default=0.0) # create an instance
Guido van Rossum7131f842007-02-09 20:13:25 +000044 >>> print(a) # show the instance
Tim Peters95c99e52001-09-03 01:24:30 +000045 {}
Guido van Rossum7131f842007-02-09 20:13:25 +000046 >>> print(type(a)) # show its type
Guido van Rossuma4cb7882001-09-25 03:56:29 +000047 <class 'test.test_descrtut.defaultdict'>
Guido van Rossum7131f842007-02-09 20:13:25 +000048 >>> print(a.__class__) # show its class
Guido van Rossuma4cb7882001-09-25 03:56:29 +000049 <class 'test.test_descrtut.defaultdict'>
Guido van Rossum7131f842007-02-09 20:13:25 +000050 >>> print(type(a) is a.__class__) # its type is its class
Guido van Rossum77f6a652002-04-03 22:41:51 +000051 True
Tim Peters95c99e52001-09-03 01:24:30 +000052 >>> a[1] = 3.25 # modify the instance
Guido van Rossum7131f842007-02-09 20:13:25 +000053 >>> print(a) # show the new value
Tim Peters95c99e52001-09-03 01:24:30 +000054 {1: 3.25}
Guido van Rossum7131f842007-02-09 20:13:25 +000055 >>> print(a[1]) # show the new item
Tim Peters95c99e52001-09-03 01:24:30 +000056 3.25
Guido van Rossum7131f842007-02-09 20:13:25 +000057 >>> print(a[0]) # a non-existant item
Tim Peters95c99e52001-09-03 01:24:30 +000058 0.0
Tim Petersa427a2b2001-10-29 22:25:45 +000059 >>> a.merge({1:100, 2:200}) # use a dict method
Guido van Rossum7131f842007-02-09 20:13:25 +000060 >>> print(sortdict(a)) # show the result
Tim Peters95c99e52001-09-03 01:24:30 +000061 {1: 3.25, 2: 200}
62 >>>
63
64We can also use the new type in contexts where classic only allows "real"
65dictionaries, such as the locals/globals dictionaries for the exec
66statement or the built-in function eval():
67
Guido van Rossum7131f842007-02-09 20:13:25 +000068 >>> print(sorted(a.keys()))
Tim Peters95c99e52001-09-03 01:24:30 +000069 [1, 2]
Georg Brandl7cae87c2006-09-06 06:51:57 +000070 >>> exec("x = 3; print x", a)
Tim Peters95c99e52001-09-03 01:24:30 +000071 3
Guido van Rossum7131f842007-02-09 20:13:25 +000072 >>> print(sorted(a.keys(), key=lambda x: (str(type(x)), x)))
Tim Peters95c99e52001-09-03 01:24:30 +000073 [1, 2, '__builtins__', 'x']
Guido van Rossum7131f842007-02-09 20:13:25 +000074 >>> print(a['x'])
Tim Peters95c99e52001-09-03 01:24:30 +000075 3
76 >>>
77
Tim Peters95c99e52001-09-03 01:24:30 +000078Now I'll show that defaultdict instances have dynamic instance variables,
79just like classic classes:
80
81 >>> a.default = -1
Guido van Rossum7131f842007-02-09 20:13:25 +000082 >>> print(a["noway"])
Tim Peters95c99e52001-09-03 01:24:30 +000083 -1
84 >>> a.default = -1000
Guido van Rossum7131f842007-02-09 20:13:25 +000085 >>> print(a["noway"])
Tim Peters95c99e52001-09-03 01:24:30 +000086 -1000
Tim Peters5d2b77c2001-09-03 05:47:38 +000087 >>> 'default' in dir(a)
Guido van Rossum77f6a652002-04-03 22:41:51 +000088 True
Tim Peters95c99e52001-09-03 01:24:30 +000089 >>> a.x1 = 100
90 >>> a.x2 = 200
Guido van Rossum7131f842007-02-09 20:13:25 +000091 >>> print(a.x1)
Tim Peters95c99e52001-09-03 01:24:30 +000092 100
Tim Peters5d2b77c2001-09-03 05:47:38 +000093 >>> d = dir(a)
94 >>> 'default' in d and 'x1' in d and 'x2' in d
Guido van Rossum77f6a652002-04-03 22:41:51 +000095 True
Guido van Rossum7131f842007-02-09 20:13:25 +000096 >>> print(sortdict(a.__dict__))
Tim Peterse2052ab2003-02-18 16:54:41 +000097 {'default': -1000, 'x1': 100, 'x2': 200}
Tim Peters95c99e52001-09-03 01:24:30 +000098 >>>
99"""
100
Tim Petersa427a2b2001-10-29 22:25:45 +0000101class defaultdict2(dict):
Tim Peters95c99e52001-09-03 01:24:30 +0000102 __slots__ = ['default']
103
104 def __init__(self, default=None):
Tim Petersa427a2b2001-10-29 22:25:45 +0000105 dict.__init__(self)
Tim Peters95c99e52001-09-03 01:24:30 +0000106 self.default = default
107
108 def __getitem__(self, key):
109 try:
Tim Petersa427a2b2001-10-29 22:25:45 +0000110 return dict.__getitem__(self, key)
Tim Peters95c99e52001-09-03 01:24:30 +0000111 except KeyError:
112 return self.default
113
114 def get(self, key, *args):
115 if not args:
116 args = (self.default,)
Tim Petersa427a2b2001-10-29 22:25:45 +0000117 return dict.get(self, key, *args)
Tim Peters95c99e52001-09-03 01:24:30 +0000118
119 def merge(self, other):
120 for key in other:
121 if key not in self:
122 self[key] = other[key]
123
124test_2 = """
125
126The __slots__ declaration takes a list of instance variables, and reserves
127space for exactly these in the instance. When __slots__ is used, other
128instance variables cannot be assigned to:
129
130 >>> a = defaultdict2(default=0.0)
131 >>> a[1]
132 0.0
133 >>> a.default = -1
134 >>> a[1]
135 -1
136 >>> a.x1 = 1
137 Traceback (most recent call last):
138 File "<stdin>", line 1, in ?
139 AttributeError: 'defaultdict2' object has no attribute 'x1'
140 >>>
141
142"""
143
144test_3 = """
145
146Introspecting instances of built-in types
147
148For instance of built-in types, x.__class__ is now the same as type(x):
149
150 >>> type([])
151 <type 'list'>
152 >>> [].__class__
153 <type 'list'>
154 >>> list
155 <type 'list'>
156 >>> isinstance([], list)
Guido van Rossum77f6a652002-04-03 22:41:51 +0000157 True
Tim Petersa427a2b2001-10-29 22:25:45 +0000158 >>> isinstance([], dict)
Guido van Rossum77f6a652002-04-03 22:41:51 +0000159 False
Tim Peters95c99e52001-09-03 01:24:30 +0000160 >>> isinstance([], object)
Guido van Rossum77f6a652002-04-03 22:41:51 +0000161 True
Tim Peters95c99e52001-09-03 01:24:30 +0000162 >>>
163
164Under the new proposal, the __methods__ attribute no longer exists:
165
166 >>> [].__methods__
167 Traceback (most recent call last):
168 File "<stdin>", line 1, in ?
169 AttributeError: 'list' object has no attribute '__methods__'
170 >>>
171
172Instead, you can get the same information from the list type:
173
174 >>> pprint.pprint(dir(list)) # like list.__dict__.keys(), but sorted
175 ['__add__',
176 '__class__',
177 '__contains__',
178 '__delattr__',
179 '__delitem__',
Guido van Rossum7b9144b2001-10-09 19:39:46 +0000180 '__delslice__',
Tim Peters80440552002-02-19 04:25:19 +0000181 '__doc__',
Tim Peters95c99e52001-09-03 01:24:30 +0000182 '__eq__',
183 '__ge__',
Guido van Rossum867a8d22001-09-21 19:29:08 +0000184 '__getattribute__',
Tim Peters95c99e52001-09-03 01:24:30 +0000185 '__getitem__',
186 '__getslice__',
187 '__gt__',
188 '__hash__',
189 '__iadd__',
190 '__imul__',
191 '__init__',
Raymond Hettinger14bd6de2002-05-31 21:40:38 +0000192 '__iter__',
Tim Peters95c99e52001-09-03 01:24:30 +0000193 '__le__',
194 '__len__',
195 '__lt__',
196 '__mul__',
197 '__ne__',
198 '__new__',
Guido van Rossum3926a632001-09-25 16:25:58 +0000199 '__reduce__',
Guido van Rossumc53f0092003-02-18 22:05:12 +0000200 '__reduce_ex__',
Tim Peters95c99e52001-09-03 01:24:30 +0000201 '__repr__',
Raymond Hettingeraf28e4b2003-11-08 12:39:53 +0000202 '__reversed__',
Tim Peters95c99e52001-09-03 01:24:30 +0000203 '__rmul__',
204 '__setattr__',
205 '__setitem__',
206 '__setslice__',
207 '__str__',
208 'append',
209 'count',
210 'extend',
211 'index',
212 'insert',
213 'pop',
214 'remove',
215 'reverse',
Raymond Hettinger64958a12003-12-17 20:43:33 +0000216 'sort']
Tim Peters95c99e52001-09-03 01:24:30 +0000217
218The new introspection API gives more information than the old one: in
219addition to the regular methods, it also shows the methods that are
220normally invoked through special notations, e.g. __iadd__ (+=), __len__
221(len), __ne__ (!=). You can invoke any method from this list directly:
222
223 >>> a = ['tic', 'tac']
224 >>> list.__len__(a) # same as len(a)
225 2
226 >>> a.__len__() # ditto
227 2
228 >>> list.append(a, 'toe') # same as a.append('toe')
229 >>> a
230 ['tic', 'tac', 'toe']
231 >>>
232
233This is just like it is for user-defined classes.
234"""
235
236test_4 = """
237
238Static methods and class methods
239
240The new introspection API makes it possible to add static methods and class
241methods. Static methods are easy to describe: they behave pretty much like
242static methods in C++ or Java. Here's an example:
243
244 >>> class C:
Guido van Rossum7131f842007-02-09 20:13:25 +0000245 ...
Guido van Rossum5a8a0372005-01-16 00:25:31 +0000246 ... @staticmethod
Tim Peters95c99e52001-09-03 01:24:30 +0000247 ... def foo(x, y):
Guido van Rossum7131f842007-02-09 20:13:25 +0000248 ... print("staticmethod", x, y)
Tim Peters95c99e52001-09-03 01:24:30 +0000249
250 >>> C.foo(1, 2)
251 staticmethod 1 2
252 >>> c = C()
253 >>> c.foo(1, 2)
254 staticmethod 1 2
255
256Class methods use a similar pattern to declare methods that receive an
257implicit first argument that is the *class* for which they are invoked.
258
259 >>> class C:
Guido van Rossum5a8a0372005-01-16 00:25:31 +0000260 ... @classmethod
Tim Peters95c99e52001-09-03 01:24:30 +0000261 ... def foo(cls, y):
Guido van Rossum7131f842007-02-09 20:13:25 +0000262 ... print("classmethod", cls, y)
Tim Peters95c99e52001-09-03 01:24:30 +0000263
264 >>> C.foo(1)
Thomas Wouters28bc7682006-04-15 09:03:16 +0000265 classmethod <class 'test.test_descrtut.C'> 1
Tim Peters95c99e52001-09-03 01:24:30 +0000266 >>> c = C()
267 >>> c.foo(1)
Thomas Wouters28bc7682006-04-15 09:03:16 +0000268 classmethod <class 'test.test_descrtut.C'> 1
Tim Peters95c99e52001-09-03 01:24:30 +0000269
270 >>> class D(C):
271 ... pass
272
273 >>> D.foo(1)
Thomas Wouters28bc7682006-04-15 09:03:16 +0000274 classmethod <class 'test.test_descrtut.D'> 1
Tim Peters95c99e52001-09-03 01:24:30 +0000275 >>> d = D()
276 >>> d.foo(1)
Thomas Wouters28bc7682006-04-15 09:03:16 +0000277 classmethod <class 'test.test_descrtut.D'> 1
Tim Peters95c99e52001-09-03 01:24:30 +0000278
279This prints "classmethod __main__.D 1" both times; in other words, the
280class passed as the first argument of foo() is the class involved in the
281call, not the class involved in the definition of foo().
282
283But notice this:
284
285 >>> class E(C):
Guido van Rossum5a8a0372005-01-16 00:25:31 +0000286 ... @classmethod
Tim Peters95c99e52001-09-03 01:24:30 +0000287 ... def foo(cls, y): # override C.foo
Guido van Rossum7131f842007-02-09 20:13:25 +0000288 ... print("E.foo() called")
Tim Peters95c99e52001-09-03 01:24:30 +0000289 ... C.foo(y)
Tim Peters95c99e52001-09-03 01:24:30 +0000290
291 >>> E.foo(1)
292 E.foo() called
Thomas Wouters28bc7682006-04-15 09:03:16 +0000293 classmethod <class 'test.test_descrtut.C'> 1
Tim Peters95c99e52001-09-03 01:24:30 +0000294 >>> e = E()
295 >>> e.foo(1)
296 E.foo() called
Thomas Wouters28bc7682006-04-15 09:03:16 +0000297 classmethod <class 'test.test_descrtut.C'> 1
Tim Peters95c99e52001-09-03 01:24:30 +0000298
299In this example, the call to C.foo() from E.foo() will see class C as its
300first argument, not class E. This is to be expected, since the call
301specifies the class C. But it stresses the difference between these class
302methods and methods defined in metaclasses (where an upcall to a metamethod
303would pass the target class as an explicit first argument).
304"""
305
306test_5 = """
307
308Attributes defined by get/set methods
309
310
Guido van Rossum8bce4ac2001-09-06 21:56:42 +0000311 >>> class property(object):
Tim Peters95c99e52001-09-03 01:24:30 +0000312 ...
313 ... def __init__(self, get, set=None):
314 ... self.__get = get
315 ... self.__set = set
316 ...
317 ... def __get__(self, inst, type=None):
318 ... return self.__get(inst)
319 ...
320 ... def __set__(self, inst, value):
321 ... if self.__set is None:
322 ... raise AttributeError, "this attribute is read-only"
323 ... return self.__set(inst, value)
324
325Now let's define a class with an attribute x defined by a pair of methods,
326getx() and and setx():
327
328 >>> class C(object):
329 ...
330 ... def __init__(self):
331 ... self.__x = 0
332 ...
333 ... def getx(self):
334 ... return self.__x
335 ...
336 ... def setx(self, x):
337 ... if x < 0: x = 0
338 ... self.__x = x
339 ...
Guido van Rossum8bce4ac2001-09-06 21:56:42 +0000340 ... x = property(getx, setx)
Tim Peters95c99e52001-09-03 01:24:30 +0000341
342Here's a small demonstration:
343
344 >>> a = C()
345 >>> a.x = 10
Guido van Rossum7131f842007-02-09 20:13:25 +0000346 >>> print(a.x)
Tim Peters95c99e52001-09-03 01:24:30 +0000347 10
348 >>> a.x = -10
Guido van Rossum7131f842007-02-09 20:13:25 +0000349 >>> print(a.x)
Tim Peters95c99e52001-09-03 01:24:30 +0000350 0
351 >>>
352
Guido van Rossum8bce4ac2001-09-06 21:56:42 +0000353Hmm -- property is builtin now, so let's try it that way too.
Tim Peters95c99e52001-09-03 01:24:30 +0000354
Guido van Rossum8bce4ac2001-09-06 21:56:42 +0000355 >>> del property # unmask the builtin
356 >>> property
357 <type 'property'>
Tim Peters95c99e52001-09-03 01:24:30 +0000358
359 >>> class C(object):
360 ... def __init__(self):
361 ... self.__x = 0
362 ... def getx(self):
363 ... return self.__x
364 ... def setx(self, x):
365 ... if x < 0: x = 0
366 ... self.__x = x
Guido van Rossum8bce4ac2001-09-06 21:56:42 +0000367 ... x = property(getx, setx)
Tim Peters95c99e52001-09-03 01:24:30 +0000368
369
370 >>> a = C()
371 >>> a.x = 10
Guido van Rossum7131f842007-02-09 20:13:25 +0000372 >>> print(a.x)
Tim Peters95c99e52001-09-03 01:24:30 +0000373 10
374 >>> a.x = -10
Guido van Rossum7131f842007-02-09 20:13:25 +0000375 >>> print(a.x)
Tim Peters95c99e52001-09-03 01:24:30 +0000376 0
377 >>>
378"""
379
380test_6 = """
381
382Method resolution order
383
384This example is implicit in the writeup.
385
Thomas Wouters28bc7682006-04-15 09:03:16 +0000386>>> class A: # implicit new-style class
Tim Peters95c99e52001-09-03 01:24:30 +0000387... def save(self):
Guido van Rossum7131f842007-02-09 20:13:25 +0000388... print("called A.save()")
Tim Peters95c99e52001-09-03 01:24:30 +0000389>>> class B(A):
390... pass
391>>> class C(A):
392... def save(self):
Guido van Rossum7131f842007-02-09 20:13:25 +0000393... print("called C.save()")
Tim Peters95c99e52001-09-03 01:24:30 +0000394>>> class D(B, C):
395... pass
396
397>>> D().save()
Thomas Wouters28bc7682006-04-15 09:03:16 +0000398called C.save()
Tim Peters95c99e52001-09-03 01:24:30 +0000399
Thomas Wouters28bc7682006-04-15 09:03:16 +0000400>>> class A(object): # explicit new-style class
Tim Peters95c99e52001-09-03 01:24:30 +0000401... def save(self):
Guido van Rossum7131f842007-02-09 20:13:25 +0000402... print("called A.save()")
Tim Peters95c99e52001-09-03 01:24:30 +0000403>>> class B(A):
404... pass
405>>> class C(A):
406... def save(self):
Guido van Rossum7131f842007-02-09 20:13:25 +0000407... print("called C.save()")
Tim Peters95c99e52001-09-03 01:24:30 +0000408>>> class D(B, C):
409... pass
410
411>>> D().save()
412called C.save()
413"""
414
415class A(object):
416 def m(self):
417 return "A"
418
419class B(A):
420 def m(self):
421 return "B" + super(B, self).m()
422
423class C(A):
424 def m(self):
425 return "C" + super(C, self).m()
426
427class D(C, B):
428 def m(self):
429 return "D" + super(D, self).m()
430
431
432test_7 = """
433
434Cooperative methods and "super"
435
Guido van Rossum7131f842007-02-09 20:13:25 +0000436>>> print(D().m()) # "DCBA"
Tim Peters95c99e52001-09-03 01:24:30 +0000437DCBA
438"""
439
440test_8 = """
441
442Backwards incompatibilities
443
444>>> class A:
445... def foo(self):
Guido van Rossum7131f842007-02-09 20:13:25 +0000446... print("called A.foo()")
Tim Peters95c99e52001-09-03 01:24:30 +0000447
448>>> class B(A):
449... pass
450
451>>> class C(A):
452... def foo(self):
453... B.foo(self)
454
455>>> C().foo()
456Traceback (most recent call last):
457 ...
458TypeError: unbound method foo() must be called with B instance as first argument (got C instance instead)
459
460>>> class C(A):
461... def foo(self):
462... A.foo(self)
463>>> C().foo()
464called A.foo()
465"""
466
467__test__ = {"tut1": test_1,
468 "tut2": test_2,
469 "tut3": test_3,
470 "tut4": test_4,
471 "tut5": test_5,
472 "tut6": test_6,
473 "tut7": test_7,
474 "tut8": test_8}
475
476# Magic test name that regrtest.py invokes *after* importing this module.
477# This worms around a bootstrap problem.
478# Note that doctest and regrtest both look in sys.argv for a "-v" argument,
479# so this works as expected in both ways of running regrtest.
Tim Petersa0a62222001-09-09 06:12:01 +0000480def test_main(verbose=None):
481 # Obscure: import this module as test.test_descrtut instead of as
482 # plain test_descrtut because the name of this module works its way
483 # into the doctest examples, and unless the full test.test_descrtut
484 # business is used the name can change depending on how the test is
485 # invoked.
Barry Warsaw04f357c2002-07-23 19:04:11 +0000486 from test import test_support, test_descrtut
487 test_support.run_doctest(test_descrtut, verbose)
Tim Peters95c99e52001-09-03 01:24:30 +0000488
489# This part isn't needed for regrtest, but for running the test directly.
490if __name__ == "__main__":
Tim Petersa0a62222001-09-09 06:12:01 +0000491 test_main(1)