ยปCore Development>Code coverage>Lib/test/test_descrtut.py

Python code coverage for Lib/test/test_descrtut.py

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