blob: b895d6dec32fc7e60bc3df4f9cb02293f15e3921 [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
39 >>> print defaultdict # show our type
Guido van Rossuma4cb7882001-09-25 03:56:29 +000040 <class 'test.test_descrtut.defaultdict'>
Tim Peters95c99e52001-09-03 01:24:30 +000041 >>> print type(defaultdict) # its metatype
42 <type 'type'>
43 >>> a = defaultdict(default=0.0) # create an instance
44 >>> print a # show the instance
45 {}
46 >>> print type(a) # show its type
Guido van Rossuma4cb7882001-09-25 03:56:29 +000047 <class 'test.test_descrtut.defaultdict'>
Tim Peters95c99e52001-09-03 01:24:30 +000048 >>> print a.__class__ # show its class
Guido van Rossuma4cb7882001-09-25 03:56:29 +000049 <class 'test.test_descrtut.defaultdict'>
Tim Peters95c99e52001-09-03 01:24:30 +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
53 >>> print a # show the new value
54 {1: 3.25}
55 >>> print a[1] # show the new item
56 3.25
57 >>> print a[0] # a non-existant item
58 0.0
Tim Petersa427a2b2001-10-29 22:25:45 +000059 >>> a.merge({1:100, 2:200}) # use a dict method
Tim Peters95c99e52001-09-03 01:24:30 +000060 >>> print sortdict(a) # show the result
61 {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
68 >>> def sorted(seq):
69 ... seq.sort()
70 ... return seq
71 >>> print sorted(a.keys())
72 [1, 2]
73 >>> exec "x = 3; print x" in a
74 3
75 >>> print sorted(a.keys())
76 [1, 2, '__builtins__', 'x']
77 >>> print a['x']
78 3
79 >>>
80
81However, our __getitem__() method is not used for variable access by the
82interpreter:
83
84 >>> exec "print foo" in a
85 Traceback (most recent call last):
86 File "<stdin>", line 1, in ?
87 File "<string>", line 1, in ?
88 NameError: name 'foo' is not defined
89 >>>
90
91Now I'll show that defaultdict instances have dynamic instance variables,
92just like classic classes:
93
94 >>> a.default = -1
95 >>> print a["noway"]
96 -1
97 >>> a.default = -1000
98 >>> print a["noway"]
99 -1000
Tim Peters5d2b77c2001-09-03 05:47:38 +0000100 >>> 'default' in dir(a)
Guido van Rossum77f6a652002-04-03 22:41:51 +0000101 True
Tim Peters95c99e52001-09-03 01:24:30 +0000102 >>> a.x1 = 100
103 >>> a.x2 = 200
104 >>> print a.x1
105 100
Tim Peters5d2b77c2001-09-03 05:47:38 +0000106 >>> d = dir(a)
107 >>> 'default' in d and 'x1' in d and 'x2' in d
Guido van Rossum77f6a652002-04-03 22:41:51 +0000108 True
Tim Peterse2052ab2003-02-18 16:54:41 +0000109 >>> print sortdict(a.__dict__)
110 {'default': -1000, 'x1': 100, 'x2': 200}
Tim Peters95c99e52001-09-03 01:24:30 +0000111 >>>
112"""
113
Tim Petersa427a2b2001-10-29 22:25:45 +0000114class defaultdict2(dict):
Tim Peters95c99e52001-09-03 01:24:30 +0000115 __slots__ = ['default']
116
117 def __init__(self, default=None):
Tim Petersa427a2b2001-10-29 22:25:45 +0000118 dict.__init__(self)
Tim Peters95c99e52001-09-03 01:24:30 +0000119 self.default = default
120
121 def __getitem__(self, key):
122 try:
Tim Petersa427a2b2001-10-29 22:25:45 +0000123 return dict.__getitem__(self, key)
Tim Peters95c99e52001-09-03 01:24:30 +0000124 except KeyError:
125 return self.default
126
127 def get(self, key, *args):
128 if not args:
129 args = (self.default,)
Tim Petersa427a2b2001-10-29 22:25:45 +0000130 return dict.get(self, key, *args)
Tim Peters95c99e52001-09-03 01:24:30 +0000131
132 def merge(self, other):
133 for key in other:
134 if key not in self:
135 self[key] = other[key]
136
137test_2 = """
138
139The __slots__ declaration takes a list of instance variables, and reserves
140space for exactly these in the instance. When __slots__ is used, other
141instance variables cannot be assigned to:
142
143 >>> a = defaultdict2(default=0.0)
144 >>> a[1]
145 0.0
146 >>> a.default = -1
147 >>> a[1]
148 -1
149 >>> a.x1 = 1
150 Traceback (most recent call last):
151 File "<stdin>", line 1, in ?
152 AttributeError: 'defaultdict2' object has no attribute 'x1'
153 >>>
154
155"""
156
157test_3 = """
158
159Introspecting instances of built-in types
160
161For instance of built-in types, x.__class__ is now the same as type(x):
162
163 >>> type([])
164 <type 'list'>
165 >>> [].__class__
166 <type 'list'>
167 >>> list
168 <type 'list'>
169 >>> isinstance([], list)
Guido van Rossum77f6a652002-04-03 22:41:51 +0000170 True
Tim Petersa427a2b2001-10-29 22:25:45 +0000171 >>> isinstance([], dict)
Guido van Rossum77f6a652002-04-03 22:41:51 +0000172 False
Tim Peters95c99e52001-09-03 01:24:30 +0000173 >>> isinstance([], object)
Guido van Rossum77f6a652002-04-03 22:41:51 +0000174 True
Tim Peters95c99e52001-09-03 01:24:30 +0000175 >>>
176
177Under the new proposal, the __methods__ attribute no longer exists:
178
179 >>> [].__methods__
180 Traceback (most recent call last):
181 File "<stdin>", line 1, in ?
182 AttributeError: 'list' object has no attribute '__methods__'
183 >>>
184
185Instead, you can get the same information from the list type:
186
187 >>> pprint.pprint(dir(list)) # like list.__dict__.keys(), but sorted
188 ['__add__',
189 '__class__',
190 '__contains__',
191 '__delattr__',
192 '__delitem__',
Guido van Rossum7b9144b2001-10-09 19:39:46 +0000193 '__delslice__',
Tim Peters80440552002-02-19 04:25:19 +0000194 '__doc__',
Tim Peters95c99e52001-09-03 01:24:30 +0000195 '__eq__',
196 '__ge__',
Guido van Rossum867a8d22001-09-21 19:29:08 +0000197 '__getattribute__',
Tim Peters95c99e52001-09-03 01:24:30 +0000198 '__getitem__',
199 '__getslice__',
200 '__gt__',
201 '__hash__',
202 '__iadd__',
203 '__imul__',
204 '__init__',
Raymond Hettinger14bd6de2002-05-31 21:40:38 +0000205 '__iter__',
Tim Peters95c99e52001-09-03 01:24:30 +0000206 '__le__',
207 '__len__',
208 '__lt__',
209 '__mul__',
210 '__ne__',
211 '__new__',
Guido van Rossum3926a632001-09-25 16:25:58 +0000212 '__reduce__',
Guido van Rossumc53f0092003-02-18 22:05:12 +0000213 '__reduce_ex__',
Tim Peters95c99e52001-09-03 01:24:30 +0000214 '__repr__',
Raymond Hettingeraf28e4b2003-11-08 12:39:53 +0000215 '__reversed__',
Tim Peters95c99e52001-09-03 01:24:30 +0000216 '__rmul__',
217 '__setattr__',
218 '__setitem__',
219 '__setslice__',
220 '__str__',
221 'append',
222 'count',
223 'extend',
224 'index',
225 'insert',
226 'pop',
227 'remove',
228 'reverse',
Raymond Hettingerc40b7af2003-10-29 07:23:57 +0000229 'sort',
230 'sorted']
Tim Peters95c99e52001-09-03 01:24:30 +0000231
232The new introspection API gives more information than the old one: in
233addition to the regular methods, it also shows the methods that are
234normally invoked through special notations, e.g. __iadd__ (+=), __len__
235(len), __ne__ (!=). You can invoke any method from this list directly:
236
237 >>> a = ['tic', 'tac']
238 >>> list.__len__(a) # same as len(a)
239 2
240 >>> a.__len__() # ditto
241 2
242 >>> list.append(a, 'toe') # same as a.append('toe')
243 >>> a
244 ['tic', 'tac', 'toe']
245 >>>
246
247This is just like it is for user-defined classes.
248"""
249
250test_4 = """
251
252Static methods and class methods
253
254The new introspection API makes it possible to add static methods and class
255methods. Static methods are easy to describe: they behave pretty much like
256static methods in C++ or Java. Here's an example:
257
258 >>> class C:
259 ...
260 ... def foo(x, y):
261 ... print "staticmethod", x, y
262 ... foo = staticmethod(foo)
263
264 >>> C.foo(1, 2)
265 staticmethod 1 2
266 >>> c = C()
267 >>> c.foo(1, 2)
268 staticmethod 1 2
269
270Class methods use a similar pattern to declare methods that receive an
271implicit first argument that is the *class* for which they are invoked.
272
273 >>> class C:
274 ... def foo(cls, y):
275 ... print "classmethod", cls, y
276 ... foo = classmethod(foo)
277
278 >>> C.foo(1)
Tim Peters90ba8d92001-09-09 01:21:31 +0000279 classmethod test.test_descrtut.C 1
Tim Peters95c99e52001-09-03 01:24:30 +0000280 >>> c = C()
281 >>> c.foo(1)
Tim Peters90ba8d92001-09-09 01:21:31 +0000282 classmethod test.test_descrtut.C 1
Tim Peters95c99e52001-09-03 01:24:30 +0000283
284 >>> class D(C):
285 ... pass
286
287 >>> D.foo(1)
Tim Peters90ba8d92001-09-09 01:21:31 +0000288 classmethod test.test_descrtut.D 1
Tim Peters95c99e52001-09-03 01:24:30 +0000289 >>> d = D()
290 >>> d.foo(1)
Tim Peters90ba8d92001-09-09 01:21:31 +0000291 classmethod test.test_descrtut.D 1
Tim Peters95c99e52001-09-03 01:24:30 +0000292
293This prints "classmethod __main__.D 1" both times; in other words, the
294class passed as the first argument of foo() is the class involved in the
295call, not the class involved in the definition of foo().
296
297But notice this:
298
299 >>> class E(C):
300 ... def foo(cls, y): # override C.foo
301 ... print "E.foo() called"
302 ... C.foo(y)
303 ... foo = classmethod(foo)
304
305 >>> E.foo(1)
306 E.foo() called
Tim Peters90ba8d92001-09-09 01:21:31 +0000307 classmethod test.test_descrtut.C 1
Tim Peters95c99e52001-09-03 01:24:30 +0000308 >>> e = E()
309 >>> e.foo(1)
310 E.foo() called
Tim Peters90ba8d92001-09-09 01:21:31 +0000311 classmethod test.test_descrtut.C 1
Tim Peters95c99e52001-09-03 01:24:30 +0000312
313In this example, the call to C.foo() from E.foo() will see class C as its
314first argument, not class E. This is to be expected, since the call
315specifies the class C. But it stresses the difference between these class
316methods and methods defined in metaclasses (where an upcall to a metamethod
317would pass the target class as an explicit first argument).
318"""
319
320test_5 = """
321
322Attributes defined by get/set methods
323
324
Guido van Rossum8bce4ac2001-09-06 21:56:42 +0000325 >>> class property(object):
Tim Peters95c99e52001-09-03 01:24:30 +0000326 ...
327 ... def __init__(self, get, set=None):
328 ... self.__get = get
329 ... self.__set = set
330 ...
331 ... def __get__(self, inst, type=None):
332 ... return self.__get(inst)
333 ...
334 ... def __set__(self, inst, value):
335 ... if self.__set is None:
336 ... raise AttributeError, "this attribute is read-only"
337 ... return self.__set(inst, value)
338
339Now let's define a class with an attribute x defined by a pair of methods,
340getx() and and setx():
341
342 >>> class C(object):
343 ...
344 ... def __init__(self):
345 ... self.__x = 0
346 ...
347 ... def getx(self):
348 ... return self.__x
349 ...
350 ... def setx(self, x):
351 ... if x < 0: x = 0
352 ... self.__x = x
353 ...
Guido van Rossum8bce4ac2001-09-06 21:56:42 +0000354 ... x = property(getx, setx)
Tim Peters95c99e52001-09-03 01:24:30 +0000355
356Here's a small demonstration:
357
358 >>> a = C()
359 >>> a.x = 10
360 >>> print a.x
361 10
362 >>> a.x = -10
363 >>> print a.x
364 0
365 >>>
366
Guido van Rossum8bce4ac2001-09-06 21:56:42 +0000367Hmm -- property is builtin now, so let's try it that way too.
Tim Peters95c99e52001-09-03 01:24:30 +0000368
Guido van Rossum8bce4ac2001-09-06 21:56:42 +0000369 >>> del property # unmask the builtin
370 >>> property
371 <type 'property'>
Tim Peters95c99e52001-09-03 01:24:30 +0000372
373 >>> class C(object):
374 ... def __init__(self):
375 ... self.__x = 0
376 ... def getx(self):
377 ... return self.__x
378 ... def setx(self, x):
379 ... if x < 0: x = 0
380 ... self.__x = x
Guido van Rossum8bce4ac2001-09-06 21:56:42 +0000381 ... x = property(getx, setx)
Tim Peters95c99e52001-09-03 01:24:30 +0000382
383
384 >>> a = C()
385 >>> a.x = 10
386 >>> print a.x
387 10
388 >>> a.x = -10
389 >>> print a.x
390 0
391 >>>
392"""
393
394test_6 = """
395
396Method resolution order
397
398This example is implicit in the writeup.
399
400>>> class A: # classic class
401... def save(self):
402... print "called A.save()"
403>>> class B(A):
404... pass
405>>> class C(A):
406... def save(self):
407... print "called C.save()"
408>>> class D(B, C):
409... pass
410
411>>> D().save()
412called A.save()
413
414>>> class A(object): # new class
415... def save(self):
416... print "called A.save()"
417>>> class B(A):
418... pass
419>>> class C(A):
420... def save(self):
421... print "called C.save()"
422>>> class D(B, C):
423... pass
424
425>>> D().save()
426called C.save()
427"""
428
429class A(object):
430 def m(self):
431 return "A"
432
433class B(A):
434 def m(self):
435 return "B" + super(B, self).m()
436
437class C(A):
438 def m(self):
439 return "C" + super(C, self).m()
440
441class D(C, B):
442 def m(self):
443 return "D" + super(D, self).m()
444
445
446test_7 = """
447
448Cooperative methods and "super"
449
450>>> print D().m() # "DCBA"
451DCBA
452"""
453
454test_8 = """
455
456Backwards incompatibilities
457
458>>> class A:
459... def foo(self):
460... print "called A.foo()"
461
462>>> class B(A):
463... pass
464
465>>> class C(A):
466... def foo(self):
467... B.foo(self)
468
469>>> C().foo()
470Traceback (most recent call last):
471 ...
472TypeError: unbound method foo() must be called with B instance as first argument (got C instance instead)
473
474>>> class C(A):
475... def foo(self):
476... A.foo(self)
477>>> C().foo()
478called A.foo()
479"""
480
481__test__ = {"tut1": test_1,
482 "tut2": test_2,
483 "tut3": test_3,
484 "tut4": test_4,
485 "tut5": test_5,
486 "tut6": test_6,
487 "tut7": test_7,
488 "tut8": test_8}
489
490# Magic test name that regrtest.py invokes *after* importing this module.
491# This worms around a bootstrap problem.
492# Note that doctest and regrtest both look in sys.argv for a "-v" argument,
493# so this works as expected in both ways of running regrtest.
Tim Petersa0a62222001-09-09 06:12:01 +0000494def test_main(verbose=None):
495 # Obscure: import this module as test.test_descrtut instead of as
496 # plain test_descrtut because the name of this module works its way
497 # into the doctest examples, and unless the full test.test_descrtut
498 # business is used the name can change depending on how the test is
499 # invoked.
Barry Warsaw04f357c2002-07-23 19:04:11 +0000500 from test import test_support, test_descrtut
501 test_support.run_doctest(test_descrtut, verbose)
Tim Peters95c99e52001-09-03 01:24:30 +0000502
503# This part isn't needed for regrtest, but for running the test directly.
504if __name__ == "__main__":
Tim Petersa0a62222001-09-09 06:12:01 +0000505 test_main(1)