summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichele Simionato <michele.simionato@gmail.com>2015-07-24 08:43:16 +0200
committerMichele Simionato <michele.simionato@gmail.com>2015-07-24 08:43:16 +0200
commit55f28695e817fd7eac8870330843b3dff8f49eaa (patch)
treeaa941ca832e82153ae8499ec557c445e86e51058
parentae96a8f0844770bfb592012ac3ad06cdc7f8e3f9 (diff)
downloadpython-decorator-git-55f28695e817fd7eac8870330843b3dff8f49eaa.tar.gz
Introduced dispatch_info
-rw-r--r--CHANGES.txt2
-rw-r--r--documentation.pdf967
-rw-r--r--documentation.rst94
-rw-r--r--src/decorator.py45
-rw-r--r--src/tests/documentation.py101
-rw-r--r--src/tests/test.py2
6 files changed, 818 insertions, 393 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index 983b266..29091b0 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -7,8 +7,8 @@ HISTORY
Reworked the documentation and introduced `decorator.decorated`.
Removed any dependence from `inspect.getargspec`, which is deprecated
in Python 3.5, as signaled by XXX.
- Copied the `__qualname__` attribute, as requested by Frazer McLean.
Fixed `contextmanager` to work with Python 3.5.
+ Copied the `__qualname__` attribute, as requested by Frazer McLean.
Added a `dispatch_on` facility to implement generic functions.
(2015/07/21)
3.4.2 Same as 3.4.1, re-uploaded to PyPI (2015-03-22)
diff --git a/documentation.pdf b/documentation.pdf
index 0166f17..fe0c2ec 100644
--- a/documentation.pdf
+++ b/documentation.pdf
@@ -127,22 +127,22 @@ endobj
<< /Border [ 0 0 0 ] /Contents () /Dest [ 70 0 R /XYZ 62.69291 445.4236 0 ] /Rect [ 521.4627 290.7736 532.5827 302.7736 ] /Subtype /Link /Type /Annot >>
endobj
43 0 obj
-<< /Border [ 0 0 0 ] /Contents () /Dest [ 72 0 R /XYZ 62.69291 503.8236 0 ] /Rect [ 62.69291 272.0236 251.0829 284.0236 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 72 0 R /XYZ 62.69291 227.0236 0 ] /Rect [ 62.69291 272.0236 251.0829 284.0236 ] /Subtype /Link /Type /Annot >>
endobj
44 0 obj
-<< /Border [ 0 0 0 ] /Contents () /Dest [ 72 0 R /XYZ 62.69291 503.8236 0 ] /Rect [ 521.4627 272.7736 532.5827 284.7736 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 72 0 R /XYZ 62.69291 227.0236 0 ] /Rect [ 521.4627 272.7736 532.5827 284.7736 ] /Subtype /Link /Type /Annot >>
endobj
45 0 obj
-<< /Border [ 0 0 0 ] /Contents () /Dest [ 75 0 R /XYZ 62.69291 729.0236 0 ] /Rect [ 62.69291 254.0236 174.3929 266.0236 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 75 0 R /XYZ 62.69291 348.6236 0 ] /Rect [ 62.69291 254.0236 174.3929 266.0236 ] /Subtype /Link /Type /Annot >>
endobj
46 0 obj
-<< /Border [ 0 0 0 ] /Contents () /Dest [ 75 0 R /XYZ 62.69291 729.0236 0 ] /Rect [ 521.4627 254.7736 532.5827 266.7736 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 75 0 R /XYZ 62.69291 348.6236 0 ] /Rect [ 521.4627 254.7736 532.5827 266.7736 ] /Subtype /Link /Type /Annot >>
endobj
47 0 obj
-<< /Border [ 0 0 0 ] /Contents () /Dest [ 77 0 R /XYZ 62.69291 180.6236 0 ] /Rect [ 62.69291 236.0236 106.0329 248.0236 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 78 0 R /XYZ 62.69291 458.6236 0 ] /Rect [ 62.69291 236.0236 106.0329 248.0236 ] /Subtype /Link /Type /Annot >>
endobj
48 0 obj
-<< /Border [ 0 0 0 ] /Contents () /Dest [ 77 0 R /XYZ 62.69291 180.6236 0 ] /Rect [ 521.4627 236.7736 532.5827 248.7736 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 78 0 R /XYZ 62.69291 458.6236 0 ] /Rect [ 521.4627 236.7736 532.5827 248.7736 ] /Subtype /Link /Type /Annot >>
endobj
49 0 obj
<< /Annots [ 5 0 R 6 0 R 7 0 R 8 0 R 9 0 R 10 0 R 11 0 R 12 0 R 13 0 R 14 0 R
@@ -248,7 +248,7 @@ endobj
/Type /Page >>
endobj
76 0 obj
-<< /A << /S /URI /Type /Action /URI (http://www.python.org/dev/peps/pep-0362) >> /Border [ 0 0 0 ] /Rect [ 301.1597 663.0236 317.8397 675.0236 ] /Subtype /Link /Type /Annot >>
+<< /A << /S /URI /Type /Action /URI (http://www.python.org/dev/peps/pep-0362) >> /Border [ 0 0 0 ] /Rect [ 301.1597 248.2236 317.8397 260.2236 ] /Subtype /Link /Type /Annot >>
endobj
77 0 obj
<< /Annots [ 76 0 R ] /Contents 120 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 101 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0
@@ -262,7 +262,7 @@ endobj
<< /Outlines 81 0 R /PageLabels 122 0 R /PageMode /UseNone /Pages 101 0 R /Type /Catalog >>
endobj
80 0 obj
-<< /Author (Michele Simionato) /CreationDate (D:20150724063304-01'00') /Creator (\(unspecified\)) /Keywords () /Producer (ReportLab PDF Library - www.reportlab.com) /Subject (\(unspecified\))
+<< /Author (Michele Simionato) /CreationDate (D:20150724083859-01'00') /Creator (\(unspecified\)) /Keywords () /Producer (ReportLab PDF Library - www.reportlab.com) /Subject (\(unspecified\))
/Title (The decorator module) >>
endobj
81 0 obj
@@ -317,13 +317,13 @@ endobj
<< /Dest [ 70 0 R /XYZ 62.69291 445.4236 0 ] /Next 98 0 R /Parent 81 0 R /Prev 96 0 R /Title (Multiple dispatch) >>
endobj
98 0 obj
-<< /Dest [ 72 0 R /XYZ 62.69291 503.8236 0 ] /Next 99 0 R /Parent 81 0 R /Prev 97 0 R /Title (Generic functions and virtual ancestors) >>
+<< /Dest [ 72 0 R /XYZ 62.69291 227.0236 0 ] /Next 99 0 R /Parent 81 0 R /Prev 97 0 R /Title (Generic functions and virtual ancestors) >>
endobj
99 0 obj
-<< /Dest [ 75 0 R /XYZ 62.69291 729.0236 0 ] /Next 100 0 R /Parent 81 0 R /Prev 98 0 R /Title (Caveats and limitations) >>
+<< /Dest [ 75 0 R /XYZ 62.69291 348.6236 0 ] /Next 100 0 R /Parent 81 0 R /Prev 98 0 R /Title (Caveats and limitations) >>
endobj
100 0 obj
-<< /Dest [ 77 0 R /XYZ 62.69291 180.6236 0 ] /Parent 81 0 R /Prev 99 0 R /Title (LICENSE) >>
+<< /Dest [ 78 0 R /XYZ 62.69291 458.6236 0 ] /Parent 81 0 R /Prev 99 0 R /Title (LICENSE) >>
endobj
101 0 obj
<< /Count 20 /Kids [ 49 0 R 52 0 R 57 0 R 58 0 R 59 0 R 61 0 R 62 0 R 63 0 R 64 0 R 65 0 R
@@ -758,7 +758,7 @@ q
q
0 0 .501961 rg
0 0 .501961 RG
-BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 60.88 0 Td (19) Tj T* -60.88 0 Td ET
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 60.88 0 Td (20) Tj T* -60.88 0 Td ET
Q
Q
q
@@ -5903,7 +5903,7 @@ Q
endstream
endobj
115 0 obj
-<< /Length 16993 >>
+<< /Length 17002 >>
stream
1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
@@ -6053,7 +6053,7 @@ q
1 0 0 1 62.69291 582.6236 cm
q
0 0 0 rg
-BT 1 0 0 1 0 38 Tm /F1 10 Tf 12 TL .352209 Tw (I could give a down-to-earth example of situations in which it is desiderable to dispatch on more than one) Tj T* 0 Tw 3.67998 Tw (argument \(for instance once I implemented a database-access library where the first dispatching) Tj T* 0 Tw .442765 Tw (argument was the the database driver and the second one was the database record\), but here I prefer to) Tj T* 0 Tw (follow the tradition and show the time-honored Rock-Paper-Scissor example:) Tj T* ET
+BT 1 0 0 1 0 38 Tm /F1 10 Tf 12 TL .352209 Tw (I could give a down-to-earth example of situations in which it is desiderable to dispatch on more than one) Tj T* 0 Tw 3.67998 Tw (argument \(for instance once I implemented a database-access library where the first dispatching) Tj T* 0 Tw .442765 Tw (argument was the the database driver and the second one was the database record\), but here I prefer to) Tj T* 0 Tw (follow the tradition and show the time-honored Rock-Paper-Scissors example:) Tj T* ET
Q
Q
q
@@ -6145,20 +6145,20 @@ q
.960784 .960784 .862745 rg
n 0 12 30 12 re f*
.960784 .960784 .862745 rg
-n 36 12 42 12 re f*
+n 36 12 48 12 re f*
.960784 .960784 .862745 rg
-n 78 12 6 12 re f*
+n 84 12 6 12 re f*
.960784 .960784 .862745 rg
-n 84 12 36 12 re f*
+n 90 12 36 12 re f*
.960784 .960784 .862745 rg
-n 120 12 12 12 re f*
+n 126 12 12 12 re f*
.960784 .960784 .862745 rg
n 24 0 42 12 re f*
.960784 .960784 .862745 rg
n 72 0 6 12 re f*
.960784 .960784 .862745 rg
n 84 0 6 12 re f*
-BT 1 0 0 1 0 14 Tm 12 TL /F5 10 Tf 0 .501961 0 rg (class) Tj /F3 10 Tf 0 0 0 rg ( ) Tj /F5 10 Tf 0 0 1 rg (Scissor) Tj /F3 10 Tf 0 0 0 rg (\() Tj 0 .501961 0 rg (object) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj 0 0 0 rg (ordinal) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (2) Tj T* ET
+BT 1 0 0 1 0 14 Tm 12 TL /F5 10 Tf 0 .501961 0 rg (class) Tj /F3 10 Tf 0 0 0 rg ( ) Tj /F5 10 Tf 0 0 1 rg (Scissors) Tj /F3 10 Tf 0 0 0 rg (\() Tj 0 .501961 0 rg (object) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj 0 0 0 rg (ordinal) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (2) Tj T* ET
Q
Q
Q
@@ -6167,7 +6167,7 @@ Q
q
1 0 0 1 62.69291 355.0236 cm
q
-BT 1 0 0 1 0 74 Tm .606235 Tw 12 TL /F1 10 Tf 0 0 0 rg (I have added an ordinal to the Rock-Paper-Scissor classes to simplify the implementation. The idea is to) Tj T* 0 Tw 1.821235 Tw (define a generic function ) Tj /F3 10 Tf 0 0 0 rg (win\(a, b\) ) Tj /F1 10 Tf 0 0 0 rg (of two arguments corresponding to the moves of the first and) Tj T* 0 Tw 1.487126 Tw (second player respectively. The moves are instances of the classes Rock, Paper and Scissors; Paper) Tj T* 0 Tw .00104 Tw (wins over Rock, Scissor wins over Paper and Rock wins over Scissor. The function will return +1 for a win,) Tj T* 0 Tw .415542 Tw (-1 for a loss and 0 for parity. There are 9 combinations, however combinations with the same ordinal \(i.e.) Tj T* 0 Tw 2.007633 Tw (the same class\) return 0; moreover by exchanging the order of the arguments the sign of the result) Tj T* 0 Tw (changes, so it is enough to specify directly only 3 implementations:) Tj T* ET
+BT 1 0 0 1 0 74 Tm .293735 Tw 12 TL /F1 10 Tf 0 0 0 rg (I have added an ordinal to the Rock-Paper-Scissors classes to simplify the implementation. The idea is to) Tj T* 0 Tw 1.821235 Tw (define a generic function ) Tj /F3 10 Tf 0 0 0 rg (win\(a, b\) ) Tj /F1 10 Tf 0 0 0 rg (of two arguments corresponding to the moves of the first and) Tj T* 0 Tw 1.487126 Tw (second player respectively. The moves are instances of the classes Rock, Paper and Scissors; Paper) Tj T* 0 Tw .587765 Tw (wins over Rock, Scissors wins over Paper and Rock wins over Scissors. The function will return +1 for a) Tj T* 0 Tw .353876 Tw (win, -1 for a loss and 0 for parity. There are 9 combinations, however combinations with the same ordinal) Tj T* 0 Tw .815542 Tw (\(i.e. the same class\) return 0; moreover by exchanging the order of the arguments the sign of the result) Tj T* 0 Tw (changes, so it is enough to specify directly only 3 implementations:) Tj T* ET
Q
Q
q
@@ -6369,30 +6369,30 @@ n 84 24 30 12 re f*
.960784 .960784 .862745 rg
n 114 24 6 12 re f*
.960784 .960784 .862745 rg
-n 126 24 42 12 re f*
+n 126 24 48 12 re f*
.960784 .960784 .862745 rg
-n 168 24 6 12 re f*
+n 174 24 6 12 re f*
.960784 .960784 .862745 rg
n 0 12 18 12 re f*
.960784 .960784 .862745 rg
-n 24 12 90 12 re f*
-.960784 .960784 .862745 rg
-n 114 12 6 12 re f*
+n 24 12 96 12 re f*
.960784 .960784 .862745 rg
n 120 12 6 12 re f*
.960784 .960784 .862745 rg
n 126 12 6 12 re f*
.960784 .960784 .862745 rg
-n 138 12 6 12 re f*
+n 132 12 6 12 re f*
.960784 .960784 .862745 rg
-n 144 12 12 12 re f*
+n 144 12 6 12 re f*
+.960784 .960784 .862745 rg
+n 150 12 12 12 re f*
.960784 .960784 .862745 rg
n 24 0 36 12 re f*
.960784 .960784 .862745 rg
n 66 0 6 12 re f*
.960784 .960784 .862745 rg
n 72 0 6 12 re f*
-BT 1 0 0 1 0 26 Tm 12 TL /F3 10 Tf .666667 .133333 1 rg (@win.register) Tj 0 0 0 rg (\() Tj 0 0 0 rg (Paper) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (Scissor) Tj 0 0 0 rg (\)) Tj 0 0 0 rg T* /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (winPaperScissor) Tj 0 0 0 rg (\() Tj 0 0 0 rg (a) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (b) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (return) Tj /F3 10 Tf 0 0 0 rg ( ) Tj .4 .4 .4 rg (-) Tj .4 .4 .4 rg (1) Tj T* ET
+BT 1 0 0 1 0 26 Tm 12 TL /F3 10 Tf .666667 .133333 1 rg (@win.register) Tj 0 0 0 rg (\() Tj 0 0 0 rg (Paper) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (Scissors) Tj 0 0 0 rg (\)) Tj 0 0 0 rg T* /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (winPaperScissors) Tj 0 0 0 rg (\() Tj 0 0 0 rg (a) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (b) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (return) Tj /F3 10 Tf 0 0 0 rg ( ) Tj .4 .4 .4 rg (-) Tj .4 .4 .4 rg (1) Tj T* ET
Q
Q
Q
@@ -6421,28 +6421,28 @@ n 84 24 24 12 re f*
.960784 .960784 .862745 rg
n 108 24 6 12 re f*
.960784 .960784 .862745 rg
-n 120 24 42 12 re f*
+n 120 24 48 12 re f*
.960784 .960784 .862745 rg
-n 162 24 6 12 re f*
+n 168 24 6 12 re f*
.960784 .960784 .862745 rg
n 0 12 18 12 re f*
.960784 .960784 .862745 rg
-n 24 12 84 12 re f*
-.960784 .960784 .862745 rg
-n 108 12 6 12 re f*
+n 24 12 90 12 re f*
.960784 .960784 .862745 rg
n 114 12 6 12 re f*
.960784 .960784 .862745 rg
n 120 12 6 12 re f*
.960784 .960784 .862745 rg
-n 132 12 6 12 re f*
+n 126 12 6 12 re f*
.960784 .960784 .862745 rg
-n 138 12 12 12 re f*
+n 138 12 6 12 re f*
+.960784 .960784 .862745 rg
+n 144 12 12 12 re f*
.960784 .960784 .862745 rg
n 24 0 36 12 re f*
.960784 .960784 .862745 rg
n 66 0 6 12 re f*
-BT 1 0 0 1 0 26 Tm 12 TL /F3 10 Tf .666667 .133333 1 rg (@win.register) Tj 0 0 0 rg (\() Tj 0 0 0 rg (Rock) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (Scissor) Tj 0 0 0 rg (\)) Tj 0 0 0 rg T* /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (winRockScissor) Tj 0 0 0 rg (\() Tj 0 0 0 rg (a) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (b) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (return) Tj /F3 10 Tf 0 0 0 rg ( ) Tj .4 .4 .4 rg (1) Tj T* ET
+BT 1 0 0 1 0 26 Tm 12 TL /F3 10 Tf .666667 .133333 1 rg (@win.register) Tj 0 0 0 rg (\() Tj 0 0 0 rg (Rock) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (Scissors) Tj 0 0 0 rg (\)) Tj 0 0 0 rg T* /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (winRockScissors) Tj 0 0 0 rg (\() Tj 0 0 0 rg (a) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (b) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (return) Tj /F3 10 Tf 0 0 0 rg ( ) Tj .4 .4 .4 rg (1) Tj T* ET
Q
Q
Q
@@ -6452,7 +6452,7 @@ Q
endstream
endobj
116 0 obj
-<< /Length 14183 >>
+<< /Length 14727 >>
stream
1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
@@ -6507,13 +6507,13 @@ n 24 180 18 12 re f*
.960784 .960784 .862745 rg
n 42 180 6 12 re f*
.960784 .960784 .862745 rg
-n 48 180 42 12 re f*
+n 48 180 48 12 re f*
.960784 .960784 .862745 rg
-n 90 180 18 12 re f*
+n 96 180 18 12 re f*
.960784 .960784 .862745 rg
-n 114 180 30 12 re f*
+n 120 180 30 12 re f*
.960784 .960784 .862745 rg
-n 144 180 18 12 re f*
+n 150 180 18 12 re f*
.960784 .960784 .862745 rg
n 0 168 6 12 re f*
.960784 .960784 .862745 rg
@@ -6531,9 +6531,9 @@ n 48 156 24 12 re f*
.960784 .960784 .862745 rg
n 72 156 18 12 re f*
.960784 .960784 .862745 rg
-n 96 156 42 12 re f*
+n 96 156 48 12 re f*
.960784 .960784 .862745 rg
-n 138 156 18 12 re f*
+n 144 156 18 12 re f*
.960784 .960784 .862745 rg
n 0 144 6 12 re f*
.960784 .960784 .862745 rg
@@ -6587,13 +6587,13 @@ n 24 84 18 12 re f*
.960784 .960784 .862745 rg
n 42 84 6 12 re f*
.960784 .960784 .862745 rg
-n 48 84 42 12 re f*
+n 48 84 48 12 re f*
.960784 .960784 .862745 rg
-n 90 84 18 12 re f*
+n 96 84 18 12 re f*
.960784 .960784 .862745 rg
-n 114 84 42 12 re f*
+n 120 84 48 12 re f*
.960784 .960784 .862745 rg
-n 156 84 18 12 re f*
+n 168 84 18 12 re f*
.960784 .960784 .862745 rg
n 0 72 6 12 re f*
.960784 .960784 .862745 rg
@@ -6633,9 +6633,9 @@ n 48 36 30 12 re f*
.960784 .960784 .862745 rg
n 78 36 18 12 re f*
.960784 .960784 .862745 rg
-n 102 36 42 12 re f*
+n 102 36 48 12 re f*
.960784 .960784 .862745 rg
-n 144 36 18 12 re f*
+n 150 36 18 12 re f*
.960784 .960784 .862745 rg
n 0 24 6 12 re f*
.960784 .960784 .862745 rg
@@ -6651,38 +6651,242 @@ n 24 12 18 12 re f*
.960784 .960784 .862745 rg
n 42 12 6 12 re f*
.960784 .960784 .862745 rg
-n 48 12 42 12 re f*
+n 48 12 48 12 re f*
.960784 .960784 .862745 rg
-n 90 12 18 12 re f*
+n 96 12 18 12 re f*
.960784 .960784 .862745 rg
-n 114 12 24 12 re f*
+n 120 12 24 12 re f*
.960784 .960784 .862745 rg
-n 138 12 18 12 re f*
+n 144 12 18 12 re f*
.960784 .960784 .862745 rg
n 0 0 6 12 re f*
.960784 .960784 .862745 rg
n 6 0 6 12 re f*
-BT 1 0 0 1 0 206 Tm 12 TL /F3 10 Tf .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (win) Tj 0 0 0 rg (\() Tj 0 0 0 rg (Paper) Tj 0 0 0 rg (\(\),) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (Rock) Tj 0 0 0 rg (\(\)\)) Tj 0 0 0 rg T* .4 .4 .4 rg (1) Tj 0 0 0 rg T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (win) Tj 0 0 0 rg (\() Tj 0 0 0 rg (Scissor) Tj 0 0 0 rg (\(\),) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (Paper) Tj 0 0 0 rg (\(\)\)) Tj 0 0 0 rg T* .4 .4 .4 rg (1) Tj 0 0 0 rg T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (win) Tj 0 0 0 rg (\() Tj 0 0 0 rg (Rock) Tj 0 0 0 rg (\(\),) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (Scissor) Tj 0 0 0 rg (\(\)\)) Tj 0 0 0 rg T* .4 .4 .4 rg (1) Tj 0 0 0 rg T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (win) Tj 0 0 0 rg (\() Tj 0 0 0 rg (Paper) Tj 0 0 0 rg (\(\),) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (Paper) Tj 0 0 0 rg (\(\)\)) Tj 0 0 0 rg T* .4 .4 .4 rg (0) Tj 0 0 0 rg T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (win) Tj 0 0 0 rg (\() Tj 0 0 0 rg (Rock) Tj 0 0 0 rg (\(\),) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (Rock) Tj 0 0 0 rg (\(\)\)) Tj 0 0 0 rg T* .4 .4 .4 rg (0) Tj 0 0 0 rg T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (win) Tj 0 0 0 rg (\() Tj 0 0 0 rg (Scissor) Tj 0 0 0 rg (\(\),) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (Scissor) Tj 0 0 0 rg (\(\)\)) Tj 0 0 0 rg T* .4 .4 .4 rg (0) Tj 0 0 0 rg T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (win) Tj 0 0 0 rg (\() Tj 0 0 0 rg (Rock) Tj 0 0 0 rg (\(\),) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (Paper) Tj 0 0 0 rg (\(\)\)) Tj 0 0 0 rg T* .4 .4 .4 rg (-) Tj .4 .4 .4 rg (1) Tj 0 0 0 rg T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (win) Tj 0 0 0 rg (\() Tj 0 0 0 rg (Paper) Tj 0 0 0 rg (\(\),) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (Scissor) Tj 0 0 0 rg (\(\)\)) Tj 0 0 0 rg T* .4 .4 .4 rg (-) Tj .4 .4 .4 rg (1) Tj 0 0 0 rg T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (win) Tj 0 0 0 rg (\() Tj 0 0 0 rg (Scissor) Tj 0 0 0 rg (\(\),) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (Rock) Tj 0 0 0 rg (\(\)\)) Tj 0 0 0 rg T* .4 .4 .4 rg (-) Tj .4 .4 .4 rg (1) Tj T* ET
+BT 1 0 0 1 0 206 Tm 12 TL /F3 10 Tf .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (win) Tj 0 0 0 rg (\() Tj 0 0 0 rg (Paper) Tj 0 0 0 rg (\(\),) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (Rock) Tj 0 0 0 rg (\(\)\)) Tj 0 0 0 rg T* .4 .4 .4 rg (1) Tj 0 0 0 rg T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (win) Tj 0 0 0 rg (\() Tj 0 0 0 rg (Scissors) Tj 0 0 0 rg (\(\),) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (Paper) Tj 0 0 0 rg (\(\)\)) Tj 0 0 0 rg T* .4 .4 .4 rg (1) Tj 0 0 0 rg T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (win) Tj 0 0 0 rg (\() Tj 0 0 0 rg (Rock) Tj 0 0 0 rg (\(\),) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (Scissors) Tj 0 0 0 rg (\(\)\)) Tj 0 0 0 rg T* .4 .4 .4 rg (1) Tj 0 0 0 rg T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (win) Tj 0 0 0 rg (\() Tj 0 0 0 rg (Paper) Tj 0 0 0 rg (\(\),) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (Paper) Tj 0 0 0 rg (\(\)\)) Tj 0 0 0 rg T* .4 .4 .4 rg (0) Tj 0 0 0 rg T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (win) Tj 0 0 0 rg (\() Tj 0 0 0 rg (Rock) Tj 0 0 0 rg (\(\),) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (Rock) Tj 0 0 0 rg (\(\)\)) Tj 0 0 0 rg T* .4 .4 .4 rg (0) Tj 0 0 0 rg T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (win) Tj 0 0 0 rg (\() Tj 0 0 0 rg (Scissors) Tj 0 0 0 rg (\(\),) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (Scissors) Tj 0 0 0 rg (\(\)\)) Tj 0 0 0 rg T* .4 .4 .4 rg (0) Tj 0 0 0 rg T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (win) Tj 0 0 0 rg (\() Tj 0 0 0 rg (Rock) Tj 0 0 0 rg (\(\),) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (Paper) Tj 0 0 0 rg (\(\)\)) Tj 0 0 0 rg T* .4 .4 .4 rg (-) Tj .4 .4 .4 rg (1) Tj 0 0 0 rg T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (win) Tj 0 0 0 rg (\() Tj 0 0 0 rg (Paper) Tj 0 0 0 rg (\(\),) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (Scissors) Tj 0 0 0 rg (\(\)\)) Tj 0 0 0 rg T* .4 .4 .4 rg (-) Tj .4 .4 .4 rg (1) Tj 0 0 0 rg T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (win) Tj 0 0 0 rg (\() Tj 0 0 0 rg (Scissors) Tj 0 0 0 rg (\(\),) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (Rock) Tj 0 0 0 rg (\(\)\)) Tj 0 0 0 rg T* .4 .4 .4 rg (-) Tj .4 .4 .4 rg (1) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 483.8236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL .76528 Tw (The point of generic functions is that they play well with subclassing. For instance, suppose we define a) Tj T* 0 Tw (StrongRock which does not lose against Paper:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 438.6236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 36 re B*
+Q
+q
+.960784 .960784 .862745 rg
+n 0 12 30 12 re f*
+.960784 .960784 .862745 rg
+n 36 12 60 12 re f*
+.960784 .960784 .862745 rg
+n 96 12 6 12 re f*
+.960784 .960784 .862745 rg
+n 102 12 24 12 re f*
+.960784 .960784 .862745 rg
+n 126 12 12 12 re f*
+.960784 .960784 .862745 rg
+n 24 0 24 12 re f*
+BT 1 0 0 1 0 14 Tm 12 TL /F5 10 Tf 0 .501961 0 rg (class) Tj /F3 10 Tf 0 0 0 rg ( ) Tj /F5 10 Tf 0 0 1 rg (StrongRock) Tj /F3 10 Tf 0 0 0 rg (\() Tj 0 0 0 rg (Rock) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (pass) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 381.4236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 48 re B*
+Q
+q
+.960784 .960784 .862745 rg
+n 0 24 78 12 re f*
+.960784 .960784 .862745 rg
+n 78 24 6 12 re f*
+.960784 .960784 .862745 rg
+n 84 24 60 12 re f*
+.960784 .960784 .862745 rg
+n 144 24 6 12 re f*
+.960784 .960784 .862745 rg
+n 156 24 30 12 re f*
+.960784 .960784 .862745 rg
+n 186 24 6 12 re f*
+.960784 .960784 .862745 rg
+n 0 12 18 12 re f*
+.960784 .960784 .862745 rg
+n 24 12 108 12 re f*
+.960784 .960784 .862745 rg
+n 132 12 6 12 re f*
+.960784 .960784 .862745 rg
+n 138 12 6 12 re f*
+.960784 .960784 .862745 rg
+n 144 12 6 12 re f*
+.960784 .960784 .862745 rg
+n 156 12 6 12 re f*
+.960784 .960784 .862745 rg
+n 162 12 12 12 re f*
+.960784 .960784 .862745 rg
+n 24 0 36 12 re f*
+.960784 .960784 .862745 rg
+n 66 0 6 12 re f*
+BT 1 0 0 1 0 26 Tm 12 TL /F3 10 Tf .666667 .133333 1 rg (@win.register) Tj 0 0 0 rg (\() Tj 0 0 0 rg (StrongRock) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (Paper) Tj 0 0 0 rg (\)) Tj 0 0 0 rg T* /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (winStrongRockPaper) Tj 0 0 0 rg (\() Tj 0 0 0 rg (a) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (b) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (return) Tj /F3 10 Tf 0 0 0 rg ( ) Tj .4 .4 .4 rg (0) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 361.4236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Then we do not need to define other implementations, since they are inherited from the parent:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 316.2236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 36 re B*
+Q
+q
+.960784 .960784 .862745 rg
+n 0 12 6 12 re f*
+.960784 .960784 .862745 rg
+n 6 12 6 12 re f*
+.960784 .960784 .862745 rg
+n 12 12 6 12 re f*
+.960784 .960784 .862745 rg
+n 24 12 18 12 re f*
+.960784 .960784 .862745 rg
+n 42 12 6 12 re f*
+.960784 .960784 .862745 rg
+n 48 12 60 12 re f*
+.960784 .960784 .862745 rg
+n 108 12 18 12 re f*
+.960784 .960784 .862745 rg
+n 132 12 48 12 re f*
+.960784 .960784 .862745 rg
+n 180 12 18 12 re f*
+.960784 .960784 .862745 rg
+n 0 0 6 12 re f*
+BT 1 0 0 1 0 14 Tm 12 TL /F3 10 Tf .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (win) Tj 0 0 0 rg (\() Tj 0 0 0 rg (StrongRock) Tj 0 0 0 rg (\(\),) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (Scissors) Tj 0 0 0 rg (\(\)\)) Tj 0 0 0 rg T* .4 .4 .4 rg (1) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 284.2236 cm
+q
+BT 1 0 0 1 0 14 Tm 12.49998 Tw 12 TL /F1 10 Tf 0 0 0 rg (You can introspect the precedence used by the dispath algorithm by calling) Tj T* 0 Tw /F3 10 Tf 0 0 0 rg (.dispatch_info\(*types\)) Tj /F1 10 Tf 0 0 0 rg (:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 239.0236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 36 re B*
+Q
+q
+.960784 .960784 .862745 rg
+n 0 12 6 12 re f*
+.960784 .960784 .862745 rg
+n 6 12 6 12 re f*
+.960784 .960784 .862745 rg
+n 12 12 6 12 re f*
+.960784 .960784 .862745 rg
+n 24 12 18 12 re f*
+.960784 .960784 .862745 rg
+n 42 12 6 12 re f*
+.960784 .960784 .862745 rg
+n 48 12 78 12 re f*
+.960784 .960784 .862745 rg
+n 126 12 6 12 re f*
+.960784 .960784 .862745 rg
+n 132 12 60 12 re f*
+.960784 .960784 .862745 rg
+n 192 12 6 12 re f*
+.960784 .960784 .862745 rg
+n 204 12 48 12 re f*
+.960784 .960784 .862745 rg
+n 252 12 6 12 re f*
+.960784 .960784 .862745 rg
+n 0 0 12 12 re f*
+.960784 .960784 .862745 rg
+n 12 0 72 12 re f*
+.960784 .960784 .862745 rg
+n 84 0 6 12 re f*
+.960784 .960784 .862745 rg
+n 96 0 60 12 re f*
+.960784 .960784 .862745 rg
+n 156 0 12 12 re f*
+.960784 .960784 .862745 rg
+n 174 0 6 12 re f*
+.960784 .960784 .862745 rg
+n 180 0 36 12 re f*
+.960784 .960784 .862745 rg
+n 216 0 6 12 re f*
+.960784 .960784 .862745 rg
+n 228 0 60 12 re f*
+.960784 .960784 .862745 rg
+n 288 0 12 12 re f*
+BT 1 0 0 1 0 14 Tm 12 TL /F3 10 Tf .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (win) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (dispatch_info) Tj 0 0 0 rg (\() Tj 0 0 0 rg (StrongRock) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (Scissors) Tj 0 0 0 rg (\)) Tj 0 0 0 rg T* 0 0 0 rg ([\() Tj .729412 .129412 .129412 rg ('StrongRock') Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj .729412 .129412 .129412 rg ('Scissors') Tj 0 0 0 rg (\),) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (\() Tj .729412 .129412 .129412 rg ('Rock') Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj .729412 .129412 .129412 rg ('Scissors') Tj 0 0 0 rg (\)]) Tj T* ET
Q
Q
Q
Q
Q
q
-1 0 0 1 62.69291 482.8236 cm
+1 0 0 1 62.69291 206.0236 cm
q
BT 1 0 0 1 0 3.5 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Generic functions and virtual ancestors) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 452.8236 cm
+1 0 0 1 62.69291 176.0236 cm
q
0 0 0 rg
BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL 1.225366 Tw (Generic function implementations in Python are complicated by the existence of "virtual ancestors", i.e.) Tj T* 0 Tw (superclasses which are not in the class hierarchy. Consider for instance this class:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 395.6236 cm
+1 0 0 1 62.69291 118.8236 cm
q
q
1 0 0 1 0 0 cm
@@ -6726,13 +6930,20 @@ Q
Q
Q
q
-1 0 0 1 62.69291 363.6236 cm
+1 0 0 1 62.69291 86.82362 cm
q
BT 1 0 0 1 0 14 Tm .772765 Tw 12 TL /F1 10 Tf 0 0 0 rg (This class defines a ) Tj /F3 10 Tf 0 0 0 rg (__len__ ) Tj /F1 10 Tf 0 0 0 rg (method and as such is considered to be a subclass of the abstract base) Tj T* 0 Tw (class ) Tj /F3 10 Tf 0 0 0 rg (collections.Sized) Tj /F1 10 Tf 0 0 0 rg (:) Tj T* ET
Q
Q
+
+endstream
+endobj
+117 0 obj
+<< /Length 12942 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 318.4236 cm
+1 0 0 1 62.69291 727.8236 cm
q
q
1 0 0 1 0 0 cm
@@ -6776,20 +6987,20 @@ Q
Q
Q
q
-1 0 0 1 62.69291 274.4236 cm
+1 0 0 1 62.69291 683.8236 cm
q
BT 1 0 0 1 0 26 Tm 2.414651 Tw 12 TL /F1 10 Tf 0 0 0 rg (However, ) Tj /F3 10 Tf 0 0 0 rg (collections.Sized ) Tj /F1 10 Tf 0 0 0 rg (is not in the MRO of ) Tj /F3 10 Tf 0 0 0 rg (WithLength) Tj /F1 10 Tf 0 0 0 rg (, it is not a true ancestor. Any) Tj T* 0 Tw .651412 Tw (implementation of generic functions, even with single dispatch, must go through some contorsion to take) Tj T* 0 Tw (into account the virtual ancestors.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 256.4236 cm
+1 0 0 1 62.69291 665.8236 cm
q
0 0 0 rg
BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (In particular if we define a generic function) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 199.2236 cm
+1 0 0 1 62.69291 608.6236 cm
q
q
1 0 0 1 0 0 cm
@@ -6841,14 +7052,14 @@ Q
Q
Q
q
-1 0 0 1 62.69291 179.2236 cm
+1 0 0 1 62.69291 588.6236 cm
q
0 0 0 rg
BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (implemented on all classes with a length) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 122.0236 cm
+1 0 0 1 62.69291 531.4236 cm
q
q
1 0 0 1 0 0 cm
@@ -6900,20 +7111,13 @@ Q
Q
Q
q
-1 0 0 1 62.69291 102.0236 cm
+1 0 0 1 62.69291 511.4236 cm
q
BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (then ) Tj /F3 10 Tf 0 0 0 rg (get_length ) Tj /F1 10 Tf 0 0 0 rg (must be defined on ) Tj /F3 10 Tf 0 0 0 rg (WithLength ) Tj /F1 10 Tf 0 0 0 rg (instances) Tj T* ET
Q
Q
-
-endstream
-endobj
-117 0 obj
-<< /Length 13146 >>
-stream
-1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 727.8236 cm
+1 0 0 1 62.69291 466.2236 cm
q
q
1 0 0 1 0 0 cm
@@ -6949,26 +7153,26 @@ Q
Q
Q
q
-1 0 0 1 62.69291 695.8236 cm
+1 0 0 1 62.69291 434.2236 cm
q
BT 1 0 0 1 0 14 Tm 2.228651 Tw 12 TL /F1 10 Tf 0 0 0 rg (even if ) Tj /F3 10 Tf 0 0 0 rg (collections.Sized ) Tj /F1 10 Tf 0 0 0 rg (is not a true ancestor of ) Tj /F3 10 Tf 0 0 0 rg (WithLength) Tj /F1 10 Tf 0 0 0 rg (. Of course this is a contrived) Tj T* 0 Tw (example since you could just use the builtin ) Tj /F3 10 Tf 0 0 0 rg (len) Tj /F1 10 Tf 0 0 0 rg (, but you should get the idea.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 653.8236 cm
+1 0 0 1 62.69291 392.2236 cm
q
BT 1 0 0 1 0 26 Tm .129461 Tw 12 TL /F1 10 Tf 0 0 0 rg (Since in Python it is possible to consider any instance of ABCMeta as a virtual ancestor of any other class) Tj T* 0 Tw .21152 Tw (\(it is enough to register it as ) Tj /F3 10 Tf 0 0 0 rg (ancestor.register\(cls\)) Tj /F1 10 Tf 0 0 0 rg (\), any implementation of generic functions must) Tj T* 0 Tw (take virtual ancestors into account. Let me give an example.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 635.8236 cm
+1 0 0 1 62.69291 374.2236 cm
q
0 0 0 rg
BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Suppose you are using a third party set-like class like the following:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 554.6236 cm
+1 0 0 1 62.69291 293.0236 cm
q
q
1 0 0 1 0 0 cm
@@ -7020,19 +7224,19 @@ Q
Q
Q
q
-1 0 0 1 62.69291 522.6236 cm
+1 0 0 1 62.69291 261.0236 cm
q
BT 1 0 0 1 0 14 Tm 1.042651 Tw 12 TL /F1 10 Tf 0 0 0 rg (Here the author of ) Tj /F3 10 Tf 0 0 0 rg (SomeSet ) Tj /F1 10 Tf 0 0 0 rg (made a mistake by not inheriting from ) Tj /F3 10 Tf 0 0 0 rg (collections.Set) Tj /F1 10 Tf 0 0 0 rg (, but only from) Tj T* 0 Tw /F3 10 Tf 0 0 0 rg (collections.Sized) Tj /F1 10 Tf 0 0 0 rg (.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 492.6236 cm
+1 0 0 1 62.69291 231.0236 cm
q
BT 1 0 0 1 0 14 Tm 1.588735 Tw 12 TL /F1 10 Tf 0 0 0 rg (This is not a problem since you can register ) Tj /F4 10 Tf (a posteriori) Tj /F1 10 Tf ( ) Tj /F3 10 Tf 0 0 0 rg (collections.Set ) Tj /F1 10 Tf 0 0 0 rg (as a virtual ancestor of) Tj T* 0 Tw /F3 10 Tf 0 0 0 rg (SomeSet) Tj /F1 10 Tf 0 0 0 rg (:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 435.4236 cm
+1 0 0 1 62.69291 173.8236 cm
q
q
1 0 0 1 0 0 cm
@@ -7102,13 +7306,13 @@ Q
Q
Q
q
-1 0 0 1 62.69291 415.4236 cm
+1 0 0 1 62.69291 153.8236 cm
q
BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (Now, let us define an implementation of ) Tj /F3 10 Tf 0 0 0 rg (get_length ) Tj /F1 10 Tf 0 0 0 rg (specific to set:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 358.2236 cm
+1 0 0 1 62.69291 96.62362 cm
q
q
1 0 0 1 0 0 cm
@@ -7153,14 +7357,21 @@ Q
Q
Q
Q
+
+endstream
+endobj
+118 0 obj
+<< /Length 12051 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 326.2236 cm
+1 0 0 1 62.69291 741.0236 cm
q
BT 1 0 0 1 0 14 Tm .210697 Tw 12 TL /F1 10 Tf 0 0 0 rg (The current implementation, as the one used by ) Tj /F3 10 Tf 0 0 0 rg (functools.singledispatch) Tj /F1 10 Tf 0 0 0 rg (, is able to discern that a) Tj T* 0 Tw /F3 10 Tf 0 0 0 rg (Set ) Tj /F1 10 Tf 0 0 0 rg (is a ) Tj /F3 10 Tf 0 0 0 rg (Sized ) Tj /F1 10 Tf 0 0 0 rg (object, so the more specific implementation for ) Tj /F3 10 Tf 0 0 0 rg (Set ) Tj /F1 10 Tf 0 0 0 rg (is taken:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 281.0236 cm
+1 0 0 1 62.69291 695.8236 cm
q
q
1 0 0 1 0 0 cm
@@ -7198,13 +7409,13 @@ Q
Q
Q
q
-1 0 0 1 62.69291 213.0236 cm
+1 0 0 1 62.69291 627.8236 cm
q
BT 1 0 0 1 0 50 Tm 3.503735 Tw 12 TL /F1 10 Tf 0 0 0 rg (Sometimes it is not clear how to dispatch. For instance, consider a class ) Tj /F3 10 Tf 0 0 0 rg (C ) Tj /F1 10 Tf 0 0 0 rg (registered both as) Tj T* 0 Tw 6.519974 Tw /F3 10 Tf 0 0 0 rg (collections.Iterable ) Tj /F1 10 Tf 0 0 0 rg (and ) Tj /F3 10 Tf 0 0 0 rg (collections.Sized ) Tj /F1 10 Tf 0 0 0 rg (and define a generic function ) Tj /F3 10 Tf 0 0 0 rg (g ) Tj /F1 10 Tf 0 0 0 rg (with) Tj T* 0 Tw 3.101085 Tw (implementations both for ) Tj /F3 10 Tf 0 0 0 rg (collections.Iterable ) Tj /F1 10 Tf 0 0 0 rg (and ) Tj /F3 10 Tf 0 0 0 rg (collections.Sized) Tj /F1 10 Tf 0 0 0 rg (. It is impossible to) Tj T* 0 Tw .690697 Tw (decide which implementation to use, since the ancestors are independent, and the following function will) Tj T* 0 Tw (raise a RuntimeError when called:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 83.82362 cm
+1 0 0 1 62.69291 414.6236 cm
q
q
1 0 0 1 0 0 cm
@@ -7214,102 +7425,75 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 468.6898 120 re B*
+n -6 -6 468.6898 204 re B*
Q
q
.960784 .960784 .862745 rg
-n 0 96 18 12 re f*
-.960784 .960784 .862745 rg
-n 24 96 138 12 re f*
+n 0 180 18 12 re f*
.960784 .960784 .862745 rg
-n 162 96 18 12 re f*
+n 24 180 138 12 re f*
.960784 .960784 .862745 rg
-n 24 84 84 12 re f*
+n 162 180 18 12 re f*
.960784 .960784 .862745 rg
-n 114 84 6 12 re f*
+n 24 168 84 12 re f*
.960784 .960784 .862745 rg
-n 126 84 66 12 re f*
+n 114 168 6 12 re f*
.960784 .960784 .862745 rg
-n 192 84 6 12 re f*
+n 126 168 66 12 re f*
.960784 .960784 .862745 rg
-n 198 84 30 12 re f*
+n 192 168 6 12 re f*
.960784 .960784 .862745 rg
-n 228 84 6 12 re f*
+n 198 168 30 12 re f*
.960784 .960784 .862745 rg
-n 24 60 90 12 re f*
+n 228 168 6 12 re f*
.960784 .960784 .862745 rg
-n 24 48 18 12 re f*
+n 24 144 90 12 re f*
.960784 .960784 .862745 rg
-n 48 48 6 12 re f*
+n 24 132 18 12 re f*
.960784 .960784 .862745 rg
-n 54 48 6 12 re f*
+n 48 132 6 12 re f*
.960784 .960784 .862745 rg
-n 60 48 18 12 re f*
+n 54 132 6 12 re f*
.960784 .960784 .862745 rg
-n 78 48 12 12 re f*
+n 60 132 18 12 re f*
.960784 .960784 .862745 rg
-n 48 36 30 12 re f*
+n 78 132 12 12 re f*
.960784 .960784 .862745 rg
-n 84 36 114 12 re f*
+n 48 120 30 12 re f*
.960784 .960784 .862745 rg
-n 198 36 6 12 re f*
+n 84 120 114 12 re f*
.960784 .960784 .862745 rg
-n 204 36 24 12 re f*
+n 198 120 6 12 re f*
.960784 .960784 .862745 rg
-n 228 36 6 12 re f*
+n 204 120 24 12 re f*
.960784 .960784 .862745 rg
-n 234 36 6 12 re f*
+n 228 120 6 12 re f*
.960784 .960784 .862745 rg
-n 240 36 12 12 re f*
+n 234 120 6 12 re f*
.960784 .960784 .862745 rg
-n 24 12 66 12 re f*
+n 240 120 12 12 re f*
.960784 .960784 .862745 rg
-n 90 12 6 12 re f*
+n 24 96 66 12 re f*
.960784 .960784 .862745 rg
-n 96 12 66 12 re f*
+n 90 96 6 12 re f*
.960784 .960784 .862745 rg
-n 162 12 6 12 re f*
+n 96 96 66 12 re f*
.960784 .960784 .862745 rg
-n 168 12 30 12 re f*
+n 162 96 6 12 re f*
.960784 .960784 .862745 rg
-n 198 12 6 12 re f*
+n 168 96 30 12 re f*
.960784 .960784 .862745 rg
-n 24 0 18 12 re f*
+n 198 96 6 12 re f*
.960784 .960784 .862745 rg
-n 48 0 42 12 re f*
+n 24 84 18 12 re f*
.960784 .960784 .862745 rg
-n 90 0 6 12 re f*
+n 48 84 42 12 re f*
.960784 .960784 .862745 rg
-n 96 0 36 12 re f*
+n 90 84 6 12 re f*
.960784 .960784 .862745 rg
-n 132 0 12 12 re f*
-BT 1 0 0 1 0 98 Tm 12 TL /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (singledispatch_example1) Tj 0 0 0 rg (\(\):) Tj 0 0 0 rg T* ( ) Tj 0 0 0 rg (singledispatch) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (dispatch_on) Tj 0 0 0 rg (\() Tj .729412 .129412 .129412 rg ('obj') Tj 0 0 0 rg (\)) Tj 0 0 0 rg T* T* ( ) Tj .666667 .133333 1 rg (@singledispatch) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (g) Tj 0 0 0 rg (\() Tj 0 0 0 rg (obj) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (raise) Tj /F3 10 Tf 0 0 0 rg ( ) Tj /F5 10 Tf .823529 .254902 .227451 rg (NotImplementedError) Tj /F3 10 Tf 0 0 0 rg (\() Tj 0 .501961 0 rg (type) Tj 0 0 0 rg (\() Tj 0 0 0 rg (g) Tj 0 0 0 rg (\)\)) Tj 0 0 0 rg T* T* ( ) Tj .666667 .133333 1 rg (@g.register) Tj 0 0 0 rg (\() Tj 0 0 0 rg (collections) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (Sized) Tj 0 0 0 rg (\)) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (g_sized) Tj 0 0 0 rg (\() Tj 0 .501961 0 rg (object) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ET
-Q
-Q
-Q
-Q
-Q
-
-endstream
-endobj
-118 0 obj
-<< /Length 12649 >>
-stream
-1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
-q
-1 0 0 1 62.69291 667.8236 cm
-q
-q
-1 0 0 1 0 0 cm
-q
-1 0 0 1 6.6 6.6 cm
-q
-.662745 .662745 .662745 RG
-.5 w
+n 96 84 36 12 re f*
.960784 .960784 .862745 rg
-n -6 -6 468.6898 96 re B*
-Q
-q
+n 132 84 12 12 re f*
.960784 .960784 .862745 rg
n 48 72 36 12 re f*
.960784 .960784 .862745 rg
@@ -7350,33 +7534,33 @@ n 36 0 6 12 re f*
n 42 0 18 12 re f*
.960784 .960784 .862745 rg
n 72 0 324 12 re f*
-BT 1 0 0 1 0 74 Tm 12 TL /F3 10 Tf 0 0 0 rg ( ) Tj /F5 10 Tf 0 .501961 0 rg (return) Tj /F3 10 Tf 0 0 0 rg ( ) Tj .729412 .129412 .129412 rg ("sized") Tj 0 0 0 rg T* T* ( ) Tj .666667 .133333 1 rg (@g.register) Tj 0 0 0 rg (\() Tj 0 0 0 rg (collections) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (Iterable) Tj 0 0 0 rg (\)) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (g_iterable) Tj 0 0 0 rg (\() Tj 0 .501961 0 rg (object) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (return) Tj /F3 10 Tf 0 0 0 rg ( ) Tj .729412 .129412 .129412 rg ("iterable") Tj 0 0 0 rg T* T* ( ) Tj 0 0 0 rg (g) Tj 0 0 0 rg (\() Tj 0 0 0 rg (C) Tj 0 0 0 rg (\(\)\)) Tj 0 0 0 rg ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# RuntimeError: Ambiguous dispatch: Iterable or Sized?) Tj T* ET
+BT 1 0 0 1 0 182 Tm 12 TL /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (singledispatch_example1) Tj 0 0 0 rg (\(\):) Tj 0 0 0 rg T* ( ) Tj 0 0 0 rg (singledispatch) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (dispatch_on) Tj 0 0 0 rg (\() Tj .729412 .129412 .129412 rg ('obj') Tj 0 0 0 rg (\)) Tj 0 0 0 rg T* T* ( ) Tj .666667 .133333 1 rg (@singledispatch) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (g) Tj 0 0 0 rg (\() Tj 0 0 0 rg (obj) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (raise) Tj /F3 10 Tf 0 0 0 rg ( ) Tj /F5 10 Tf .823529 .254902 .227451 rg (NotImplementedError) Tj /F3 10 Tf 0 0 0 rg (\() Tj 0 .501961 0 rg (type) Tj 0 0 0 rg (\() Tj 0 0 0 rg (g) Tj 0 0 0 rg (\)\)) Tj 0 0 0 rg T* T* ( ) Tj .666667 .133333 1 rg (@g.register) Tj 0 0 0 rg (\() Tj 0 0 0 rg (collections) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (Sized) Tj 0 0 0 rg (\)) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (g_sized) Tj 0 0 0 rg (\() Tj 0 .501961 0 rg (object) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (return) Tj /F3 10 Tf 0 0 0 rg ( ) Tj .729412 .129412 .129412 rg ("sized") Tj 0 0 0 rg T* T* ( ) Tj .666667 .133333 1 rg (@g.register) Tj 0 0 0 rg (\() Tj 0 0 0 rg (collections) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (Iterable) Tj 0 0 0 rg (\)) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (g_iterable) Tj 0 0 0 rg (\() Tj 0 .501961 0 rg (object) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (return) Tj /F3 10 Tf 0 0 0 rg ( ) Tj .729412 .129412 .129412 rg ("iterable") Tj 0 0 0 rg T* T* ( ) Tj 0 0 0 rg (g) Tj 0 0 0 rg (\() Tj 0 0 0 rg (C) Tj 0 0 0 rg (\(\)\)) Tj 0 0 0 rg ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# RuntimeError: Ambiguous dispatch: Iterable or Sized?) Tj T* ET
Q
Q
Q
Q
Q
q
-1 0 0 1 62.69291 635.8236 cm
+1 0 0 1 62.69291 382.6236 cm
q
BT 1 0 0 1 0 14 Tm .745433 Tw 12 TL /F1 10 Tf 0 0 0 rg (This is consistent with the "refuse the temptation to guess" philosophy. ) Tj /F3 10 Tf 0 0 0 rg (functools.singledispatch) Tj T* 0 Tw /F1 10 Tf 0 0 0 rg (would raise a similar error.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 557.8236 cm
+1 0 0 1 62.69291 304.6236 cm
q
0 0 0 rg
BT 1 0 0 1 0 62 Tm /F1 10 Tf 12 TL .01104 Tw (It would be easy to rely on the order of registration to decide the precedence order. This is reasonable, but) Tj T* 0 Tw 3.788555 Tw (also fragile: if during some refactoring you change the registration order by mistake, a different) Tj T* 0 Tw 3.585814 Tw (implementation could be taken. If implementations of the generic functions are distributed across) Tj T* 0 Tw .939984 Tw (modules, and you change the import order, a different implementation could be taken. So the decorator) Tj T* 0 Tw .128935 Tw (module prefers to raise an error in the face of ambiguity. This is the same approach taken by the standard) Tj T* 0 Tw (library.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 491.8236 cm
+1 0 0 1 62.69291 238.6236 cm
q
BT 1 0 0 1 0 50 Tm .743735 Tw 12 TL /F1 10 Tf 0 0 0 rg (However, it should be noticed that the dispatch algorithm used by the decorator module is different from) Tj T* 0 Tw 2.269398 Tw (the one used by the standard library, so there are cases where you will get different answers. The) Tj T* 0 Tw 1.830814 Tw (difference is that ) Tj /F3 10 Tf 0 0 0 rg (functools.singledispatch ) Tj /F1 10 Tf 0 0 0 rg (tries to insert the virtual ancestors ) Tj /F4 10 Tf (before ) Tj /F1 10 Tf (the base) Tj T* 0 Tw 1.149983 Tw (classes, whereas ) Tj /F3 10 Tf 0 0 0 rg (decorator.dispatch_on ) Tj /F1 10 Tf 0 0 0 rg (tries to insert them ) Tj /F4 10 Tf (after ) Tj /F1 10 Tf (the base classes. I will give an) Tj T* 0 Tw (example showing the difference:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 146.6236 cm
+1 0 0 1 62.69291 85.42362 cm
q
q
1 0 0 1 0 0 cm
@@ -7386,177 +7570,220 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 468.6898 336 re B*
+n -6 -6 468.6898 144 re B*
Q
q
.960784 .960784 .862745 rg
-n 0 312 18 12 re f*
+n 0 120 18 12 re f*
+.960784 .960784 .862745 rg
+n 24 120 138 12 re f*
.960784 .960784 .862745 rg
-n 24 312 138 12 re f*
+n 162 120 18 12 re f*
.960784 .960784 .862745 rg
-n 162 312 18 12 re f*
+n 24 108 294 12 re f*
.960784 .960784 .862745 rg
-n 24 300 294 12 re f*
+n 24 96 84 12 re f*
.960784 .960784 .862745 rg
-n 24 288 84 12 re f*
+n 114 96 6 12 re f*
.960784 .960784 .862745 rg
-n 114 288 6 12 re f*
+n 126 96 66 12 re f*
.960784 .960784 .862745 rg
-n 126 288 66 12 re f*
+n 192 96 6 12 re f*
.960784 .960784 .862745 rg
-n 192 288 6 12 re f*
+n 198 96 30 12 re f*
.960784 .960784 .862745 rg
-n 198 288 30 12 re f*
+n 228 96 6 12 re f*
.960784 .960784 .862745 rg
-n 228 288 6 12 re f*
+n 24 72 30 12 re f*
.960784 .960784 .862745 rg
-n 24 264 30 12 re f*
+n 60 72 6 12 re f*
.960784 .960784 .862745 rg
-n 60 264 6 12 re f*
+n 66 72 6 12 re f*
.960784 .960784 .862745 rg
-n 66 264 6 12 re f*
+n 72 72 36 12 re f*
.960784 .960784 .862745 rg
-n 72 264 36 12 re f*
+n 108 72 12 12 re f*
.960784 .960784 .862745 rg
-n 108 264 12 12 re f*
+n 48 60 24 12 re f*
.960784 .960784 .862745 rg
-n 48 252 24 12 re f*
+n 24 36 30 12 re f*
.960784 .960784 .862745 rg
-n 24 228 30 12 re f*
+n 60 36 6 12 re f*
.960784 .960784 .862745 rg
-n 60 228 6 12 re f*
+n 66 36 6 12 re f*
.960784 .960784 .862745 rg
-n 66 228 6 12 re f*
+n 72 36 6 12 re f*
.960784 .960784 .862745 rg
-n 72 228 6 12 re f*
+n 78 36 6 12 re f*
.960784 .960784 .862745 rg
-n 78 228 6 12 re f*
+n 84 36 30 12 re f*
.960784 .960784 .862745 rg
-n 84 228 30 12 re f*
+n 114 36 6 12 re f*
.960784 .960784 .862745 rg
-n 114 228 6 12 re f*
+n 126 36 6 12 re f*
.960784 .960784 .862745 rg
-n 126 228 6 12 re f*
+n 132 36 12 12 re f*
.960784 .960784 .862745 rg
-n 132 228 12 12 re f*
+n 48 24 18 12 re f*
.960784 .960784 .862745 rg
-n 48 216 18 12 re f*
+n 72 24 42 12 re f*
.960784 .960784 .862745 rg
-n 72 216 42 12 re f*
+n 114 24 6 12 re f*
.960784 .960784 .862745 rg
-n 114 216 6 12 re f*
+n 120 24 24 12 re f*
.960784 .960784 .862745 rg
-n 120 216 24 12 re f*
+n 144 24 12 12 re f*
.960784 .960784 .862745 rg
-n 144 216 12 12 re f*
+n 72 12 36 12 re f*
.960784 .960784 .862745 rg
-n 72 204 36 12 re f*
+n 114 12 6 12 re f*
+BT 1 0 0 1 0 122 Tm 12 TL /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (singledispatch_example2) Tj 0 0 0 rg (\(\):) Tj 0 0 0 rg T* ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# adapted from functools.singledispatch test case) Tj /F3 10 Tf 0 0 0 rg T* ( ) Tj 0 0 0 rg (singledispatch) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (dispatch_on) Tj 0 0 0 rg (\() Tj .729412 .129412 .129412 rg ('arg') Tj 0 0 0 rg (\)) Tj 0 0 0 rg T* T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (class) Tj /F3 10 Tf 0 0 0 rg ( ) Tj /F5 10 Tf 0 0 1 rg (S) Tj /F3 10 Tf 0 0 0 rg (\() Tj 0 .501961 0 rg (object) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (pass) Tj /F3 10 Tf 0 0 0 rg T* T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (class) Tj /F3 10 Tf 0 0 0 rg ( ) Tj /F5 10 Tf 0 0 1 rg (V) Tj /F3 10 Tf 0 0 0 rg (\() Tj 0 0 0 rg (c) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (Sized) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (S) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (__len__) Tj 0 0 0 rg (\() Tj 0 .501961 0 rg (self) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (return) Tj /F3 10 Tf 0 0 0 rg ( ) Tj .4 .4 .4 rg (0) Tj 0 0 0 rg T* T* ET
+Q
+Q
+Q
+Q
+Q
+
+endstream
+endobj
+119 0 obj
+<< /Length 10875 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 547.8236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
.960784 .960784 .862745 rg
-n 114 204 6 12 re f*
+n -6 -6 468.6898 216 re B*
+Q
+q
.960784 .960784 .862745 rg
-n 24 180 90 12 re f*
+n 24 192 90 12 re f*
.960784 .960784 .862745 rg
-n 24 168 18 12 re f*
+n 24 180 18 12 re f*
.960784 .960784 .862745 rg
-n 48 168 6 12 re f*
+n 48 180 6 12 re f*
.960784 .960784 .862745 rg
-n 54 168 6 12 re f*
+n 54 180 6 12 re f*
.960784 .960784 .862745 rg
-n 60 168 18 12 re f*
+n 60 180 18 12 re f*
.960784 .960784 .862745 rg
-n 78 168 12 12 re f*
+n 78 180 12 12 re f*
.960784 .960784 .862745 rg
-n 48 156 36 12 re f*
+n 48 168 36 12 re f*
.960784 .960784 .862745 rg
-n 90 156 36 12 re f*
+n 90 168 36 12 re f*
.960784 .960784 .862745 rg
-n 24 132 66 12 re f*
+n 24 144 66 12 re f*
.960784 .960784 .862745 rg
-n 90 132 6 12 re f*
+n 90 144 6 12 re f*
.960784 .960784 .862745 rg
-n 96 132 6 12 re f*
+n 96 144 6 12 re f*
.960784 .960784 .862745 rg
-n 102 132 6 12 re f*
+n 102 144 6 12 re f*
.960784 .960784 .862745 rg
-n 24 120 18 12 re f*
+n 24 132 18 12 re f*
.960784 .960784 .862745 rg
-n 48 120 18 12 re f*
+n 48 132 18 12 re f*
.960784 .960784 .862745 rg
-n 66 120 6 12 re f*
+n 66 132 6 12 re f*
.960784 .960784 .862745 rg
-n 72 120 18 12 re f*
+n 72 132 18 12 re f*
.960784 .960784 .862745 rg
-n 90 120 12 12 re f*
+n 90 132 12 12 re f*
.960784 .960784 .862745 rg
-n 48 108 36 12 re f*
+n 48 120 36 12 re f*
.960784 .960784 .862745 rg
-n 90 108 18 12 re f*
+n 90 120 18 12 re f*
.960784 .960784 .862745 rg
-n 24 84 66 12 re f*
+n 24 96 66 12 re f*
.960784 .960784 .862745 rg
-n 90 84 6 12 re f*
+n 90 96 6 12 re f*
.960784 .960784 .862745 rg
-n 96 84 6 12 re f*
+n 96 96 6 12 re f*
.960784 .960784 .862745 rg
-n 102 84 6 12 re f*
+n 102 96 6 12 re f*
.960784 .960784 .862745 rg
-n 108 84 54 12 re f*
+n 108 96 54 12 re f*
.960784 .960784 .862745 rg
-n 162 84 6 12 re f*
+n 162 96 6 12 re f*
.960784 .960784 .862745 rg
-n 24 72 18 12 re f*
+n 24 84 18 12 re f*
.960784 .960784 .862745 rg
-n 48 72 66 12 re f*
+n 48 84 66 12 re f*
.960784 .960784 .862745 rg
-n 114 72 6 12 re f*
+n 114 84 6 12 re f*
.960784 .960784 .862745 rg
-n 120 72 18 12 re f*
+n 120 84 18 12 re f*
.960784 .960784 .862745 rg
-n 138 72 12 12 re f*
+n 138 84 12 12 re f*
.960784 .960784 .862745 rg
-n 48 60 36 12 re f*
+n 48 72 36 12 re f*
.960784 .960784 .862745 rg
-n 90 60 66 12 re f*
+n 90 72 66 12 re f*
.960784 .960784 .862745 rg
-n 24 36 6 12 re f*
+n 24 48 6 12 re f*
.960784 .960784 .862745 rg
-n 36 36 6 12 re f*
+n 36 48 6 12 re f*
.960784 .960784 .862745 rg
-n 48 36 6 12 re f*
+n 48 48 6 12 re f*
.960784 .960784 .862745 rg
-n 54 36 12 12 re f*
+n 54 48 12 12 re f*
.960784 .960784 .862745 rg
-n 24 24 36 12 re f*
+n 24 36 36 12 re f*
.960784 .960784 .862745 rg
-n 66 24 6 12 re f*
+n 66 36 6 12 re f*
.960784 .960784 .862745 rg
-n 72 24 6 12 re f*
+n 72 36 6 12 re f*
.960784 .960784 .862745 rg
-n 78 24 6 12 re f*
+n 78 36 6 12 re f*
.960784 .960784 .862745 rg
-n 84 24 6 12 re f*
+n 84 36 6 12 re f*
.960784 .960784 .862745 rg
-n 96 24 12 12 re f*
+n 96 36 12 12 re f*
.960784 .960784 .862745 rg
-n 114 24 18 12 re f*
+n 114 36 18 12 re f*
.960784 .960784 .862745 rg
-n 24 12 6 12 re f*
+n 24 24 6 12 re f*
.960784 .960784 .862745 rg
-n 30 12 6 12 re f*
+n 30 24 6 12 re f*
.960784 .960784 .862745 rg
-n 36 12 54 12 re f*
+n 36 24 54 12 re f*
.960784 .960784 .862745 rg
-n 90 12 6 12 re f*
+n 90 24 6 12 re f*
.960784 .960784 .862745 rg
-n 96 12 48 12 re f*
+n 96 24 48 12 re f*
.960784 .960784 .862745 rg
-n 144 12 6 12 re f*
+n 144 24 6 12 re f*
.960784 .960784 .862745 rg
-n 150 12 6 12 re f*
+n 150 24 6 12 re f*
.960784 .960784 .862745 rg
-n 156 12 6 12 re f*
+n 156 24 6 12 re f*
+.960784 .960784 .862745 rg
+n 174 24 246 12 re f*
+.960784 .960784 .862745 rg
+n 24 12 36 12 re f*
+.960784 .960784 .862745 rg
+n 66 12 6 12 re f*
+.960784 .960784 .862745 rg
+n 72 12 6 12 re f*
.960784 .960784 .862745 rg
-n 174 12 246 12 re f*
+n 78 12 6 12 re f*
+.960784 .960784 .862745 rg
+n 84 12 6 12 re f*
+.960784 .960784 .862745 rg
+n 96 12 12 12 re f*
+.960784 .960784 .862745 rg
+n 114 12 18 12 re f*
+.960784 .960784 .862745 rg
+n 144 12 294 12 re f*
.960784 .960784 .862745 rg
n 24 0 36 12 re f*
.960784 .960784 .862745 rg
@@ -7564,51 +7791,126 @@ n 66 0 6 12 re f*
.960784 .960784 .862745 rg
n 72 0 6 12 re f*
.960784 .960784 .862745 rg
-n 78 0 6 12 re f*
-.960784 .960784 .862745 rg
n 84 0 6 12 re f*
+BT 1 0 0 1 0 194 Tm 12 TL /F3 10 Tf 0 0 0 rg ( ) Tj .666667 .133333 1 rg (@singledispatch) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (g) Tj 0 0 0 rg (\() Tj 0 0 0 rg (arg) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (return) Tj /F3 10 Tf 0 0 0 rg ( ) Tj .729412 .129412 .129412 rg ("base") Tj 0 0 0 rg T* T* ( ) Tj .666667 .133333 1 rg (@g.register) Tj 0 0 0 rg (\() Tj 0 0 0 rg (S) Tj 0 0 0 rg (\)) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (g_s) Tj 0 0 0 rg (\() Tj 0 0 0 rg (arg) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (return) Tj /F3 10 Tf 0 0 0 rg ( ) Tj .729412 .129412 .129412 rg ("s") Tj 0 0 0 rg T* T* ( ) Tj .666667 .133333 1 rg (@g.register) Tj 0 0 0 rg (\() Tj 0 0 0 rg (c) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (Container) Tj 0 0 0 rg (\)) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (g_container) Tj 0 0 0 rg (\() Tj 0 0 0 rg (arg) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (return) Tj /F3 10 Tf 0 0 0 rg ( ) Tj .729412 .129412 .129412 rg ("container") Tj 0 0 0 rg T* T* ( ) Tj 0 0 0 rg (v) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (V) Tj 0 0 0 rg (\(\)) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (assert) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 0 rg (g) Tj 0 0 0 rg (\() Tj 0 0 0 rg (v) Tj 0 0 0 rg (\)) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (==) Tj 0 0 0 rg ( ) Tj .729412 .129412 .129412 rg ("s") Tj 0 0 0 rg T* ( ) Tj 0 0 0 rg (c) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (Container) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (register) Tj 0 0 0 rg (\() Tj 0 0 0 rg (V) Tj 0 0 0 rg (\)) Tj 0 0 0 rg ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# add c.Container to the virtual mro of V) Tj /F3 10 Tf 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (assert) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 0 rg (g) Tj 0 0 0 rg (\() Tj 0 0 0 rg (v) Tj 0 0 0 rg (\)) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (==) Tj 0 0 0 rg ( ) Tj .729412 .129412 .129412 rg ("s") Tj 0 0 0 rg ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# since the virtual mro is V, Sized, S, Container) Tj /F3 10 Tf 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (return) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 0 rg (g) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (V) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 479.8236 cm
+q
+BT 1 0 0 1 0 50 Tm 10.88816 Tw 12 TL /F1 10 Tf 0 0 0 rg (If you play with this example and replace the ) Tj /F3 10 Tf 0 0 0 rg (singledispatch ) Tj /F1 10 Tf 0 0 0 rg (definition with) Tj T* 0 Tw 2.720888 Tw /F3 10 Tf 0 0 0 rg (functools.singledispatch) Tj /F1 10 Tf 0 0 0 rg (, the assert will break: ) Tj /F3 10 Tf 0 0 0 rg (g ) Tj /F1 10 Tf 0 0 0 rg (will return ) Tj /F3 10 Tf 0 0 0 rg ("container" ) Tj /F1 10 Tf 0 0 0 rg (instead of ) Tj /F3 10 Tf 0 0 0 rg ("s") Tj /F1 10 Tf 0 0 0 rg (,) Tj T* 0 Tw .779147 Tw (because ) Tj /F3 10 Tf 0 0 0 rg (functools.singledispatch ) Tj /F1 10 Tf 0 0 0 rg (will insert the ) Tj /F3 10 Tf 0 0 0 rg (Container ) Tj /F1 10 Tf 0 0 0 rg (class right before ) Tj /F3 10 Tf 0 0 0 rg (S) Tj /F1 10 Tf 0 0 0 rg (. The only way) Tj T* 0 Tw .259431 Tw (to understand what is happening here is to scratch your head by looking at the implementations. I will just) Tj T* 0 Tw (notice that ) Tj /F3 10 Tf 0 0 0 rg (.dispatch_info ) Tj /F1 10 Tf 0 0 0 rg (is quite useful:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 422.6236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 48 re B*
+Q
+q
+.960784 .960784 .862745 rg
+n 0 24 6 12 re f*
+.960784 .960784 .862745 rg
+n 6 24 6 12 re f*
+.960784 .960784 .862745 rg
+n 12 24 6 12 re f*
+.960784 .960784 .862745 rg
+n 24 24 6 12 re f*
+.960784 .960784 .862745 rg
+n 30 24 6 12 re f*
+.960784 .960784 .862745 rg
+n 42 24 6 12 re f*
+.960784 .960784 .862745 rg
+n 54 24 6 12 re f*
+.960784 .960784 .862745 rg
+n 66 24 138 12 re f*
+.960784 .960784 .862745 rg
+n 204 24 12 12 re f*
+.960784 .960784 .862745 rg
+n 0 12 6 12 re f*
+.960784 .960784 .862745 rg
+n 6 12 6 12 re f*
+.960784 .960784 .862745 rg
+n 12 12 6 12 re f*
+.960784 .960784 .862745 rg
+n 24 12 6 12 re f*
+.960784 .960784 .862745 rg
+n 30 12 6 12 re f*
+.960784 .960784 .862745 rg
+n 36 12 78 12 re f*
+.960784 .960784 .862745 rg
+n 114 12 6 12 re f*
+.960784 .960784 .862745 rg
+n 120 12 6 12 re f*
+.960784 .960784 .862745 rg
+n 126 12 6 12 re f*
+.960784 .960784 .862745 rg
+n 0 0 12 12 re f*
+.960784 .960784 .862745 rg
+n 12 0 18 12 re f*
+.960784 .960784 .862745 rg
+n 30 0 18 12 re f*
+.960784 .960784 .862745 rg
+n 54 0 6 12 re f*
+.960784 .960784 .862745 rg
+n 60 0 42 12 re f*
+.960784 .960784 .862745 rg
+n 102 0 18 12 re f*
.960784 .960784 .862745 rg
-n 102 0 324 12 re f*
-BT 1 0 0 1 0 314 Tm 12 TL /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (singledispatch_example2) Tj 0 0 0 rg (\(\):) Tj 0 0 0 rg T* ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# adapted from functools.singledispatch test case) Tj /F3 10 Tf 0 0 0 rg T* ( ) Tj 0 0 0 rg (singledispatch) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (dispatch_on) Tj 0 0 0 rg (\() Tj .729412 .129412 .129412 rg ('arg') Tj 0 0 0 rg (\)) Tj 0 0 0 rg T* T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (class) Tj /F3 10 Tf 0 0 0 rg ( ) Tj /F5 10 Tf 0 0 1 rg (S) Tj /F3 10 Tf 0 0 0 rg (\() Tj 0 .501961 0 rg (object) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (pass) Tj /F3 10 Tf 0 0 0 rg T* T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (class) Tj /F3 10 Tf 0 0 0 rg ( ) Tj /F5 10 Tf 0 0 1 rg (V) Tj /F3 10 Tf 0 0 0 rg (\() Tj 0 0 0 rg (c) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (Sized) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (S) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (__len__) Tj 0 0 0 rg (\() Tj 0 .501961 0 rg (self) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (return) Tj /F3 10 Tf 0 0 0 rg ( ) Tj .4 .4 .4 rg (0) Tj 0 0 0 rg T* T* ( ) Tj .666667 .133333 1 rg (@singledispatch) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (j) Tj 0 0 0 rg (\() Tj 0 0 0 rg (arg) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (return) Tj /F3 10 Tf 0 0 0 rg ( ) Tj .729412 .129412 .129412 rg ("base") Tj 0 0 0 rg T* T* ( ) Tj .666667 .133333 1 rg (@j.register) Tj 0 0 0 rg (\() Tj 0 0 0 rg (S) Tj 0 0 0 rg (\)) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (j_s) Tj 0 0 0 rg (\() Tj 0 0 0 rg (arg) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (return) Tj /F3 10 Tf 0 0 0 rg ( ) Tj .729412 .129412 .129412 rg ("s") Tj 0 0 0 rg T* T* ( ) Tj .666667 .133333 1 rg (@j.register) Tj 0 0 0 rg (\() Tj 0 0 0 rg (c) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (Container) Tj 0 0 0 rg (\)) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (j_container) Tj 0 0 0 rg (\() Tj 0 0 0 rg (arg) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (return) Tj /F3 10 Tf 0 0 0 rg ( ) Tj .729412 .129412 .129412 rg ("container") Tj 0 0 0 rg T* T* ( ) Tj 0 0 0 rg (v) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (V) Tj 0 0 0 rg (\(\)) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (assert) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 0 rg (j) Tj 0 0 0 rg (\() Tj 0 0 0 rg (v) Tj 0 0 0 rg (\)) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (==) Tj 0 0 0 rg ( ) Tj .729412 .129412 .129412 rg ("s") Tj 0 0 0 rg T* ( ) Tj 0 0 0 rg (c) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (Container) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (register) Tj 0 0 0 rg (\() Tj 0 0 0 rg (V) Tj 0 0 0 rg (\)) Tj 0 0 0 rg ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# add c.Container to the virtual mro of V) Tj /F3 10 Tf 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (return) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 0 rg (j) Tj 0 0 0 rg (\() Tj 0 0 0 rg (v) Tj 0 0 0 rg (\)) Tj 0 0 0 rg ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# "s", since the virtual mro is V, Sized, S, Container) Tj T* ET
+n 126 0 6 12 re f*
+.960784 .960784 .862745 rg
+n 132 0 18 12 re f*
+.960784 .960784 .862745 rg
+n 150 0 18 12 re f*
+.960784 .960784 .862745 rg
+n 174 0 6 12 re f*
+.960784 .960784 .862745 rg
+n 180 0 66 12 re f*
+.960784 .960784 .862745 rg
+n 246 0 18 12 re f*
+BT 1 0 0 1 0 26 Tm 12 TL /F3 10 Tf .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (g) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (V) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (singledispatch_example2) Tj 0 0 0 rg (\(\)) Tj 0 0 0 rg T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (g) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (dispatch_info) Tj 0 0 0 rg (\() Tj 0 0 0 rg (V) Tj 0 0 0 rg (\)) Tj 0 0 0 rg T* 0 0 0 rg ([\() Tj .729412 .129412 .129412 rg ('V') Tj 0 0 0 rg (,\),) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (\() Tj .729412 .129412 .129412 rg ('Sized') Tj 0 0 0 rg (,\),) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (\() Tj .729412 .129412 .129412 rg ('S') Tj 0 0 0 rg (,\),) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (\() Tj .729412 .129412 .129412 rg ('Container') Tj 0 0 0 rg (,\)]) Tj T* ET
Q
Q
Q
Q
Q
q
-1 0 0 1 62.69291 102.6236 cm
+1 0 0 1 62.69291 390.6236 cm
q
-BT 1 0 0 1 0 26 Tm 10.88816 Tw 12 TL /F1 10 Tf 0 0 0 rg (If you play with this example and replace the ) Tj /F3 10 Tf 0 0 0 rg (singledispatch ) Tj /F1 10 Tf 0 0 0 rg (definition with) Tj T* 0 Tw 1.433615 Tw /F3 10 Tf 0 0 0 rg (functools.singledispatch) Tj /F1 10 Tf 0 0 0 rg (, you will see the output change from ) Tj /F3 10 Tf 0 0 0 rg ("s" ) Tj /F1 10 Tf 0 0 0 rg (to ) Tj /F3 10 Tf 0 0 0 rg ("container") Tj /F1 10 Tf 0 0 0 rg (, because) Tj T* 0 Tw /F3 10 Tf 0 0 0 rg (functools.singledispatch ) Tj /F1 10 Tf 0 0 0 rg (will insert the ) Tj /F3 10 Tf 0 0 0 rg (Container ) Tj /F1 10 Tf 0 0 0 rg (class right before ) Tj /F3 10 Tf 0 0 0 rg (S) Tj /F1 10 Tf 0 0 0 rg (.) Tj T* ET
+BT 1 0 0 1 0 14 Tm 1.086136 Tw 12 TL /F1 10 Tf 0 0 0 rg (The current implementation does not implement any kind of cooperation between generic functions, i.e.) Tj T* 0 Tw (there is nothing akin to call-next-method in Lisp, nor akin to ) Tj /F3 10 Tf 0 0 0 rg (super ) Tj /F1 10 Tf 0 0 0 rg (in Python.) Tj T* ET
Q
Q
-
-endstream
-endobj
-119 0 obj
-<< /Length 9358 >>
-stream
-1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 741.0236 cm
+1 0 0 1 62.69291 360.6236 cm
q
-BT 1 0 0 1 0 14 Tm .39561 Tw 12 TL /F1 10 Tf 0 0 0 rg (Finally let me notice that the decorator module implementation does not use any cache, whereas the one) Tj T* 0 Tw (in ) Tj /F3 10 Tf 0 0 0 rg (singledispatch ) Tj /F1 10 Tf 0 0 0 rg (has a cache.) Tj T* ET
+BT 1 0 0 1 0 14 Tm .22186 Tw 12 TL /F1 10 Tf 0 0 0 rg (Finally, let me notice that the decorator module implementation does not use any cache, whereas the one) Tj T* 0 Tw (in ) Tj /F3 10 Tf 0 0 0 rg (singledispatch ) Tj /F1 10 Tf 0 0 0 rg (has a cache.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 708.0236 cm
+1 0 0 1 62.69291 327.6236 cm
q
BT 1 0 0 1 0 3.5 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Caveats and limitations) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 678.0236 cm
+1 0 0 1 62.69291 297.6236 cm
q
0 0 0 rg
BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL .259431 Tw (One thing you should be aware of, is the performance penalty of decorators. The worse case is shown by) Tj T* 0 Tw (the following example:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 452.8236 cm
+1 0 0 1 62.69291 96.42362 cm
q
q
1 0 0 1 0 0 cm
@@ -7618,24 +7920,52 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 468.6898 216 re B*
+n -6 -6 468.6898 192 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 170 Tm /F3 10 Tf 12 TL ($ cat performance.sh) Tj T* (python3 -m timeit -s ") Tj T* (from decorator import decorator) Tj T* T* (@decorator) Tj T* (def do_nothing\(func, *args, **kw\):) Tj T* ( return func\(*args, **kw\)) Tj T* T* (@do_nothing) Tj T* (def f\(\):) Tj T* ( pass) Tj T* (" "f\(\)") Tj T* T* (python3 -m timeit -s ") Tj T* (def f\(\):) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+
+endstream
+endobj
+120 0 obj
+<< /Length 11972 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 727.8236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 36 re B*
Q
q
0 0 0 rg
-BT 1 0 0 1 0 194 Tm /F3 10 Tf 12 TL ($ cat performance.sh) Tj T* (python3 -m timeit -s ") Tj T* (from decorator import decorator) Tj T* T* (@decorator) Tj T* (def do_nothing\(func, *args, **kw\):) Tj T* ( return func\(*args, **kw\)) Tj T* T* (@do_nothing) Tj T* (def f\(\):) Tj T* ( pass) Tj T* (" "f\(\)") Tj T* T* (python3 -m timeit -s ") Tj T* (def f\(\):) Tj T* ( pass) Tj T* (" "f\(\)") Tj T* ET
+BT 1 0 0 1 0 14 Tm /F3 10 Tf 12 TL ( pass) Tj T* (" "f\(\)") Tj T* ET
Q
Q
Q
Q
Q
q
-1 0 0 1 62.69291 432.8236 cm
+1 0 0 1 62.69291 707.8236 cm
q
BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (On my laptop, using the ) Tj /F3 10 Tf 0 0 0 rg (do_nothing ) Tj /F1 10 Tf 0 0 0 rg (decorator instead of the plain function is five times slower:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 375.6236 cm
+1 0 0 1 62.69291 650.6236 cm
q
q
1 0 0 1 0 0 cm
@@ -7656,20 +7986,20 @@ Q
Q
Q
q
-1 0 0 1 62.69291 331.6236 cm
+1 0 0 1 62.69291 606.6236 cm
q
BT 1 0 0 1 0 26 Tm 1.25832 Tw 12 TL /F1 10 Tf 0 0 0 rg (It should be noted that a real life function would probably do something more useful than ) Tj /F3 10 Tf 0 0 0 rg (f ) Tj /F1 10 Tf 0 0 0 rg (here, and) Tj T* 0 Tw .91811 Tw (therefore in real life the performance penalty could be completely negligible. As always, the only way to) Tj T* 0 Tw (know if there is a penalty in your specific use case is to measure it.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 301.6236 cm
+1 0 0 1 62.69291 576.6236 cm
q
0 0 0 rg
BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL .091984 Tw (More importantly, you should be aware that decorators will make your tracebacks longer and more difficult) Tj T* 0 Tw (to understand. Consider this example:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 244.4236 cm
+1 0 0 1 62.69291 519.4236 cm
q
q
1 0 0 1 0 0 cm
@@ -7713,13 +8043,13 @@ Q
Q
Q
q
-1 0 0 1 62.69291 212.4236 cm
+1 0 0 1 62.69291 487.4236 cm
q
BT 1 0 0 1 0 14 Tm .583318 Tw 12 TL /F1 10 Tf 0 0 0 rg (Calling ) Tj /F3 10 Tf 0 0 0 rg (f\(\) ) Tj /F1 10 Tf 0 0 0 rg (will give you a ) Tj /F3 10 Tf 0 0 0 rg (ZeroDivisionError) Tj /F1 10 Tf 0 0 0 rg (, but since the function is decorated the traceback will) Tj T* 0 Tw (be longer:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 83.22362 cm
+1 0 0 1 62.69291 358.2236 cm
q
q
1 0 0 1 0 0 cm
@@ -7866,39 +8196,39 @@ Q
Q
Q
Q
-
-endstream
-endobj
-120 0 obj
-<< /Length 13207 >>
-stream
-1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 705.0236 cm
+1 0 0 1 62.69291 290.2236 cm
q
BT 1 0 0 1 0 50 Tm 1.05528 Tw 12 TL /F1 10 Tf 0 0 0 rg (You see here the inner call to the decorator ) Tj /F3 10 Tf 0 0 0 rg (trace) Tj /F1 10 Tf 0 0 0 rg (, which calls ) Tj /F3 10 Tf 0 0 0 rg (f\(*args,) Tj ( ) Tj (**kw\)) Tj /F1 10 Tf 0 0 0 rg (, and a reference to) Tj T* 0 Tw .076457 Tw /F3 10 Tf 0 0 0 rg (File) Tj ( ) Tj (") Tj (<) Tj (string) Tj (>) Tj (",) Tj ( ) Tj (line) Tj ( ) Tj (2,) Tj ( ) Tj (in) Tj ( ) Tj (f) Tj /F1 10 Tf 0 0 0 rg (. This latter reference is due to the fact that internally the decorator) Tj T* 0 Tw 2.053318 Tw (module uses ) Tj /F3 10 Tf 0 0 0 rg (exec ) Tj /F1 10 Tf 0 0 0 rg (to generate the decorated function. Notice that ) Tj /F3 10 Tf 0 0 0 rg (exec ) Tj /F1 10 Tf 0 0 0 rg (is ) Tj /F4 10 Tf (not ) Tj /F1 10 Tf (responsibile for the) Tj T* 0 Tw 1.507485 Tw (performance penalty, since is the called ) Tj /F4 10 Tf (only once ) Tj /F1 10 Tf (at function decoration time, and not every time the) Tj T* 0 Tw (decorated function is called.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 579.0236 cm
+1 0 0 1 62.69291 164.2236 cm
q
BT 1 0 0 1 0 110 Tm .932209 Tw 12 TL /F1 10 Tf 0 0 0 rg (At present, there is no clean way to avoid ) Tj /F3 10 Tf 0 0 0 rg (exec) Tj /F1 10 Tf 0 0 0 rg (. A clean solution would require to change the CPython) Tj T* 0 Tw .777485 Tw (implementation of functions and add an hook to make it possible to change their signature directly. That) Tj T* 0 Tw .74186 Tw (could happen in future versions of Python \(see PEP ) Tj 0 0 .501961 rg (362) Tj 0 0 0 rg (\) and then the decorator module would become) Tj T* 0 Tw 2.385318 Tw (obsolete. However, at present, even in Python 3.5 it is impossible to change the function signature) Tj T* 0 Tw 1.372485 Tw (directly, therefore the ) Tj /F3 10 Tf 0 0 0 rg (decorator ) Tj /F1 10 Tf 0 0 0 rg (module is still useful. Actually, this is the main reasons why I keep) Tj T* 0 Tw 2.169398 Tw (maintaining the module and releasing new versions. It should be noticed that in Python 3.5 a lot of) Tj T* 0 Tw 9.189147 Tw (improvements have been made: in that version you can decorated a function with) Tj T* 0 Tw .084147 Tw /F3 10 Tf 0 0 0 rg (func_tools.update_wrapper ) Tj /F1 10 Tf 0 0 0 rg (and ) Tj /F3 10 Tf 0 0 0 rg (pydoc ) Tj /F1 10 Tf 0 0 0 rg (will see the correct signature; still internally the function will) Tj T* 0 Tw 1.47748 Tw (have an incorrect signature, as you can see by using ) Tj /F3 10 Tf 0 0 0 rg (inspect.getfullargspec) Tj /F1 10 Tf 0 0 0 rg (: all documentation) Tj T* 0 Tw (tools using such function \(which has been correctly deprecated\) will see the wrong signature.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 525.0236 cm
+1 0 0 1 62.69291 110.2236 cm
q
BT 1 0 0 1 0 38 Tm 1.043828 Tw 12 TL /F1 10 Tf 0 0 0 rg (In the present implementation, decorators generated by ) Tj /F3 10 Tf 0 0 0 rg (decorator ) Tj /F1 10 Tf 0 0 0 rg (can only be used on user-defined) Tj T* 0 Tw .152485 Tw (Python functions or methods, not on generic callable objects, nor on built-in functions, due to limitations of) Tj T* 0 Tw 2.15881 Tw (the ) Tj /F3 10 Tf 0 0 0 rg (inspect ) Tj /F1 10 Tf 0 0 0 rg (module in the standard library, especially for Python 2.X \(in Python 3.5 a lot of such) Tj T* 0 Tw (limitations have been removed\).) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 495.0236 cm
+1 0 0 1 62.69291 80.22362 cm
q
BT 1 0 0 1 0 14 Tm .785777 Tw 12 TL /F1 10 Tf 0 0 0 rg (There is a restriction on the names of the arguments: for instance, if try to call an argument ) Tj /F3 10 Tf 0 0 0 rg (_call_ ) Tj /F1 10 Tf 0 0 0 rg (or) Tj T* 0 Tw /F3 10 Tf 0 0 0 rg (_func_ ) Tj /F1 10 Tf 0 0 0 rg (you will get a ) Tj /F3 10 Tf 0 0 0 rg (NameError) Tj /F1 10 Tf 0 0 0 rg (:) Tj T* ET
Q
Q
+
+endstream
+endobj
+121 0 obj
+<< /Length 11599 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 377.8236 cm
+1 0 0 1 62.69291 655.8236 cm
q
q
1 0 0 1 0 0 cm
@@ -8000,14 +8330,14 @@ Q
Q
Q
q
-1 0 0 1 62.69291 345.8236 cm
+1 0 0 1 62.69291 623.8236 cm
q
0 0 0 rg
BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL 1.720651 Tw (Finally, the implementation is such that the decorated function makes a \(shallow\) copy of the original) Tj T* 0 Tw (function dictionary:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 192.6236 cm
+1 0 0 1 62.69291 470.6236 cm
q
q
1 0 0 1 0 0 cm
@@ -8147,37 +8477,30 @@ Q
Q
Q
q
-1 0 0 1 62.69291 159.6236 cm
+1 0 0 1 62.69291 437.6236 cm
q
BT 1 0 0 1 0 3.5 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (LICENSE) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 141.6236 cm
+1 0 0 1 62.69291 419.6236 cm
q
0 0 0 rg
BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Copyright \(c\) 2005-2015, Michele Simionato All rights reserved.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 111.6236 cm
+1 0 0 1 62.69291 389.6236 cm
q
0 0 0 rg
BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL 1.328555 Tw (Redistribution and use in source and binary forms, with or without modification, are permitted provided) Tj T* 0 Tw (that the following conditions are met:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 105.6236 cm
+1 0 0 1 62.69291 383.6236 cm
Q
-
-endstream
-endobj
-121 0 obj
-<< /Length 2070 >>
-stream
-1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 717.0236 cm
+1 0 0 1 62.69291 335.6236 cm
0 0 0 rg
BT /F1 10 Tf 12 TL ET
BT 1 0 0 1 0 2 Tm T* ET
@@ -8192,17 +8515,17 @@ q
Q
Q
q
-1 0 0 1 62.69291 717.0236 cm
+1 0 0 1 62.69291 335.6236 cm
Q
q
-1 0 0 1 62.69291 591.0236 cm
+1 0 0 1 62.69291 209.6236 cm
q
0 0 0 rg
BT 1 0 0 1 0 110 Tm /F1 10 Tf 12 TL .17998 Tw (THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND) Tj T* 0 Tw 2.911797 Tw (ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED) Tj T* 0 Tw 5.165529 Tw (WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE) Tj T* 0 Tw 1.395433 Tw (DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE) Tj T* 0 Tw 5.53122 Tw (FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL) Tj T* 0 Tw 2.705976 Tw (DAMAGES \(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR) Tj T* 0 Tw 3.868976 Tw (SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION\) HOWEVER) Tj T* 0 Tw 1.326647 Tw (CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR) Tj T* 0 Tw 1.525366 Tw (TORT \(INCLUDING NEGLIGENCE OR OTHERWISE\) ARISING IN ANY WAY OUT OF THE USE OF) Tj T* 0 Tw (THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 561.0236 cm
+1 0 0 1 62.69291 179.6236 cm
q
0 0 0 rg
BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL .407132 Tw (If you use this software and you are happy with it, consider sending me a note, just to gratify my ego. On) Tj T* 0 Tw (the other hand, if you use this software and you are unhappy with it, send me a patch!) Tj T* ET
@@ -8395,38 +8718,38 @@ xref
0000185132 00000 n
0000201743 00000 n
0000214158 00000 n
-0000231210 00000 n
-0000245452 00000 n
-0000258657 00000 n
-0000271365 00000 n
-0000280781 00000 n
-0000294047 00000 n
-0000296175 00000 n
-0000296433 00000 n
-0000296471 00000 n
-0000296509 00000 n
-0000296547 00000 n
-0000296585 00000 n
-0000296623 00000 n
-0000296661 00000 n
-0000296699 00000 n
-0000296737 00000 n
-0000296775 00000 n
-0000296814 00000 n
-0000296853 00000 n
-0000296892 00000 n
-0000296931 00000 n
-0000296970 00000 n
-0000297009 00000 n
-0000297048 00000 n
-0000297087 00000 n
-0000297126 00000 n
-0000297165 00000 n
+0000231219 00000 n
+0000246005 00000 n
+0000259006 00000 n
+0000271116 00000 n
+0000282050 00000 n
+0000294081 00000 n
+0000305739 00000 n
+0000305997 00000 n
+0000306035 00000 n
+0000306073 00000 n
+0000306111 00000 n
+0000306149 00000 n
+0000306187 00000 n
+0000306225 00000 n
+0000306263 00000 n
+0000306301 00000 n
+0000306339 00000 n
+0000306378 00000 n
+0000306417 00000 n
+0000306456 00000 n
+0000306495 00000 n
+0000306534 00000 n
+0000306573 00000 n
+0000306612 00000 n
+0000306651 00000 n
+0000306690 00000 n
+0000306729 00000 n
trailer
<< /ID
% ReportLab generated PDF document -- digest (http://www.reportlab.com)
- [(\224\356\312\274\343M$\177\006\323\247~\206\006\340\240) (\224\356\312\274\343M$\177\006\323\247~\206\006\340\240)]
+ [(\030J\344-\350Q?\316/-\332\001\315\307\)\243) (\030J\344-\350Q?\316/-\332\001\315\307\)\243)]
/Info 80 0 R /Root 79 0 R /Size 143 >>
startxref
-297204
+306768
%%EOF
diff --git a/documentation.rst b/documentation.rst
index c33d5f0..5b0c5da 100644
--- a/documentation.rst
+++ b/documentation.rst
@@ -915,7 +915,7 @@ to dispatch on more than one argument (for instance once I implemented
a database-access library where the first dispatching argument was the
the database driver and the second one was the database record),
but here I prefer to follow the tradition and show the time-honored
-Rock-Paper-Scissor example:
+Rock-Paper-Scissors example:
.. code-block:: python
@@ -929,16 +929,16 @@ Rock-Paper-Scissor example:
.. code-block:: python
- class Scissor(object):
+ class Scissors(object):
ordinal = 2
-I have added an ordinal to the Rock-Paper-Scissor classes to simplify
+I have added an ordinal to the Rock-Paper-Scissors classes to simplify
the implementation. The idea is to define a generic function ``win(a,
b)`` of two arguments corresponding to the moves of the first and
second player respectively. The moves are instances of the classes
-Rock, Paper and Scissors; Paper wins over Rock, Scissor wins over
-Paper and Rock wins over Scissor. The function will return +1 for a
+Rock, Paper and Scissors; Paper wins over Rock, Scissors wins over
+Paper and Rock wins over Scissors. The function will return +1 for a
win, -1 for a loss and 0 for parity. There are 9 combinations, however
combinations with the same ordinal (i.e. the same class) return 0;
moreover by exchanging the order of the arguments the sign of the
@@ -963,14 +963,14 @@ implementations:
.. code-block:: python
- @win.register(Paper, Scissor)
- def winPaperScissor(a, b):
+ @win.register(Paper, Scissors)
+ def winPaperScissors(a, b):
return -1
.. code-block:: python
- @win.register(Rock, Scissor)
- def winRockScissor(a, b):
+ @win.register(Rock, Scissors)
+ def winRockScissors(a, b):
return 1
@@ -980,23 +980,55 @@ Here is the result:
>>> win(Paper(), Rock())
1
- >>> win(Scissor(), Paper())
+ >>> win(Scissors(), Paper())
1
- >>> win(Rock(), Scissor())
+ >>> win(Rock(), Scissors())
1
>>> win(Paper(), Paper())
0
>>> win(Rock(), Rock())
0
- >>> win(Scissor(), Scissor())
+ >>> win(Scissors(), Scissors())
0
>>> win(Rock(), Paper())
-1
- >>> win(Paper(), Scissor())
+ >>> win(Paper(), Scissors())
-1
- >>> win(Scissor(), Rock())
+ >>> win(Scissors(), Rock())
-1
+The point of generic functions is that they play well with subclassing.
+For instance, suppose we define a StrongRock which does not lose against
+Paper:
+
+.. code-block:: python
+
+ class StrongRock(Rock):
+ pass
+
+.. code-block:: python
+
+ @win.register(StrongRock, Paper)
+ def winStrongRockPaper(a, b):
+ return 0
+
+
+Then we do not need to define other implementations, since they are
+inherited from the parent:
+
+.. code-block:: python
+
+ >>> win(StrongRock(), Scissors())
+ 1
+
+You can introspect the precedence used by the dispath algorithm by
+calling ``.dispatch_info(*types)``:
+
+.. code-block:: python
+
+ >>> win.dispatch_info(StrongRock, Scissors)
+ [('StrongRock', 'Scissors'), ('Rock', 'Scissors')]
+
Generic functions and virtual ancestors
-------------------------------------------------
@@ -1162,29 +1194,43 @@ I will give an example showing the difference:
return 0
@singledispatch
- def j(arg):
+ def g(arg):
return "base"
- @j.register(S)
- def j_s(arg):
+ @g.register(S)
+ def g_s(arg):
return "s"
- @j.register(c.Container)
- def j_container(arg):
+ @g.register(c.Container)
+ def g_container(arg):
return "container"
v = V()
- assert j(v) == "s"
+ assert g(v) == "s"
c.Container.register(V) # add c.Container to the virtual mro of V
- return j(v) # "s", since the virtual mro is V, Sized, S, Container
+ assert g(v) == "s" # since the virtual mro is V, Sized, S, Container
+ return g, V
If you play with this example and replace the ``singledispatch`` definition
-with ``functools.singledispatch``, you will see the output change from ``"s"``
-to ``"container"``, because ``functools.singledispatch``
+with ``functools.singledispatch``, the assert will break: ``g`` will return
+``"container"`` instead of ``"s"``, because ``functools.singledispatch``
will insert the ``Container`` class right before ``S``.
+The only way to understand what is happening here is to scratch your
+head by looking at the implementations. I will just notice that
+``.dispatch_info`` is quite useful:
+
+.. code-block:: python
+
+ >>> g, V = singledispatch_example2()
+ >>> g.dispatch_info(V)
+ [('V',), ('Sized',), ('S',), ('Container',)]
+
+The current implementation does not implement any kind of cooperation
+between generic functions, i.e. there is nothing akin to call-next-method
+in Lisp, nor akin to ``super`` in Python.
-Finally let me notice that the decorator module implementation does
+Finally, let me notice that the decorator module implementation does
not use any cache, whereas the one in ``singledispatch`` has a cache.
Caveats and limitations
diff --git a/src/decorator.py b/src/decorator.py
index 7e03d42..8faee1f 100644
--- a/src/decorator.py
+++ b/src/decorator.py
@@ -38,6 +38,7 @@ __version__ = '4.0.0'
import re
import sys
import inspect
+import operator
import itertools
import collections
@@ -318,11 +319,11 @@ def dispatch_on(*dispatch_args):
assert dispatch_args, 'No dispatch args passed'
dispatch_str = '(%s,)' % ', '.join(dispatch_args)
- def check(types):
- """Make use one passes the expected number of types"""
- if len(types) != len(dispatch_args):
- raise TypeError('Expected %d types, got %d' %
- (len(dispatch_args), len(types)))
+ def check(arguments, wrong=operator.ne, msg=''):
+ """Make sure one passes the expected number of arguments"""
+ if wrong(len(arguments), len(dispatch_args)):
+ raise TypeError('Expected %d arguments, got %d%s' %
+ (len(dispatch_args), len(arguments), msg))
def gen_func_dec(func):
"""Decorator turning a function into a generic function"""
@@ -346,7 +347,7 @@ def dispatch_on(*dispatch_args):
append(type_, ra)
return [set(ra) for ra in ras]
- def vmros(*types):
+ def ancestors(*types):
"""
Get a list of virtual MROs, one for each type
"""
@@ -362,25 +363,31 @@ def dispatch_on(*dispatch_args):
mro = type('t', (t, va), {}).__mro__[1:]
else:
mro = t.__mro__
- lists.append(mro[:-1]) # discard object
+ lists.append(mro[:-1]) # discard t and object
return lists
def register(*types):
- "Decorator to register an implementation for the given types"
+ """
+ Decorator to register an implementation for the given types
+ """
check(types)
-
def dec(f):
- n_args = len(getfullargspec(f).args)
- if n_args < len(dispatch_args):
- raise TypeError(
- '%s has not enough arguments (got %d, expected %d)' %
- (f, n_args, len(dispatch_args)))
+ check(getfullargspec(f).args, operator.lt, ' in ' + f.__name__)
typemap[types] = f
return f
return dec
+ def dispatch_info(*types):
+ """
+ An utility to introspect the dispatch algorithm
+ """
+ check(types)
+ lst = []
+ for anc in itertools.product(*ancestors(*types)):
+ lst.append(tuple(a.__name__ for a in anc))
+ return lst
+
def _dispatch(dispatch_args, *args, **kw):
- "Dispatcher function"
types = tuple(type(arg) for arg in dispatch_args)
try: # fast path
f = typemap[types]
@@ -388,7 +395,9 @@ def dispatch_on(*dispatch_args):
pass
else:
return f(*args, **kw)
- for types_ in itertools.product(*vmros(*types)):
+ combinations = itertools.product(*ancestors(*types))
+ next(combinations) # the first one has been already tried
+ for types_ in combinations:
f = typemap.get(types_)
if f is not None:
return f(*args, **kw)
@@ -399,8 +408,8 @@ def dispatch_on(*dispatch_args):
return FunctionMaker.create(
func, 'return _f_(%s, %%(shortsignature)s)' % dispatch_str,
dict(_f_=_dispatch), register=register, default=func,
- typemap=typemap, vancestors=vancestors, vmros=vmros,
- __wrapped__=func)
+ typemap=typemap, vancestors=vancestors, ancestors=ancestors,
+ dispatch_info=dispatch_info, __wrapped__=func)
gen_func_dec.__name__ = 'dispatch_on' + dispatch_str
return gen_func_dec
diff --git a/src/tests/documentation.py b/src/tests/documentation.py
index 89dd6ec..04ee70e 100644
--- a/src/tests/documentation.py
+++ b/src/tests/documentation.py
@@ -700,18 +700,18 @@ to dispatch on more than one argument (for instance once I implemented
a database-access library where the first dispatching argument was the
the database driver and the second one was the database record),
but here I prefer to follow the tradition and show the time-honored
-Rock-Paper-Scissor example:
+Rock-Paper-Scissors example:
$$Rock
$$Paper
-$$Scissor
+$$Scissors
-I have added an ordinal to the Rock-Paper-Scissor classes to simplify
+I have added an ordinal to the Rock-Paper-Scissors classes to simplify
the implementation. The idea is to define a generic function ``win(a,
b)`` of two arguments corresponding to the moves of the first and
second player respectively. The moves are instances of the classes
-Rock, Paper and Scissors; Paper wins over Rock, Scissor wins over
-Paper and Rock wins over Scissor. The function will return +1 for a
+Rock, Paper and Scissors; Paper wins over Rock, Scissors wins over
+Paper and Rock wins over Scissors. The function will return +1 for a
win, -1 for a loss and 0 for parity. There are 9 combinations, however
combinations with the same ordinal (i.e. the same class) return 0;
moreover by exchanging the order of the arguments the sign of the
@@ -720,8 +720,8 @@ implementations:
$$win
$$winRockPaper
-$$winPaperScissor
-$$winRockScissor
+$$winPaperScissors
+$$winRockScissors
Here is the result:
@@ -729,23 +729,46 @@ Here is the result:
>>> win(Paper(), Rock())
1
- >>> win(Scissor(), Paper())
+ >>> win(Scissors(), Paper())
1
- >>> win(Rock(), Scissor())
+ >>> win(Rock(), Scissors())
1
>>> win(Paper(), Paper())
0
>>> win(Rock(), Rock())
0
- >>> win(Scissor(), Scissor())
+ >>> win(Scissors(), Scissors())
0
>>> win(Rock(), Paper())
-1
- >>> win(Paper(), Scissor())
+ >>> win(Paper(), Scissors())
-1
- >>> win(Scissor(), Rock())
+ >>> win(Scissors(), Rock())
-1
+The point of generic functions is that they play well with subclassing.
+For instance, suppose we define a StrongRock which does not lose against
+Paper:
+
+$$StrongRock
+$$winStrongRockPaper
+
+Then we do not need to define other implementations, since they are
+inherited from the parent:
+
+.. code-block:: python
+
+ >>> win(StrongRock(), Scissors())
+ 1
+
+You can introspect the precedence used by the dispath algorithm by
+calling ``.dispatch_info(*types)``:
+
+.. code-block:: python
+
+ >>> win.dispatch_info(StrongRock, Scissors)
+ [('StrongRock', 'Scissors'), ('Rock', 'Scissors')]
+
Generic functions and virtual ancestors
-------------------------------------------------
@@ -855,11 +878,24 @@ I will give an example showing the difference:
$$singledispatch_example2
If you play with this example and replace the ``singledispatch`` definition
-with ``functools.singledispatch``, you will see the output change from ``"s"``
-to ``"container"``, because ``functools.singledispatch``
+with ``functools.singledispatch``, the assert will break: ``g`` will return
+``"container"`` instead of ``"s"``, because ``functools.singledispatch``
will insert the ``Container`` class right before ``S``.
+The only way to understand what is happening here is to scratch your
+head by looking at the implementations. I will just notice that
+``.dispatch_info`` is quite useful:
-Finally let me notice that the decorator module implementation does
+.. code-block:: python
+
+ >>> g, V = singledispatch_example2()
+ >>> g.dispatch_info(V)
+ [('V',), ('Sized',), ('S',), ('Container',)]
+
+The current implementation does not implement any kind of cooperation
+between generic functions, i.e. there is nothing akin to call-next-method
+in Lisp, nor akin to ``super`` in Python.
+
+Finally, let me notice that the decorator module implementation does
not use any cache, whereas the one in ``singledispatch`` has a cache.
Caveats and limitations
@@ -1411,10 +1447,14 @@ class Paper(object):
ordinal = 1
-class Scissor(object):
+class Scissors(object):
ordinal = 2
+class StrongRock(Rock):
+ pass
+
+
@dispatch_on('a', 'b')
def win(a, b):
if a.ordinal == b.ordinal:
@@ -1429,16 +1469,21 @@ def winRockPaper(a, b):
return -1
-@win.register(Rock, Scissor)
-def winRockScissor(a, b):
+@win.register(Rock, Scissors)
+def winRockScissors(a, b):
return 1
-@win.register(Paper, Scissor)
-def winPaperScissor(a, b):
+@win.register(Paper, Scissors)
+def winPaperScissors(a, b):
return -1
+@win.register(StrongRock, Paper)
+def winStrongRockPaper(a, b):
+ return 0
+
+
class WithLength(object):
def __len__(self):
return 0
@@ -1502,21 +1547,23 @@ def singledispatch_example2():
return 0
@singledispatch
- def j(arg):
+ def g(arg):
return "base"
- @j.register(S)
- def j_s(arg):
+ @g.register(S)
+ def g_s(arg):
return "s"
- @j.register(c.Container)
- def j_container(arg):
+ @g.register(c.Container)
+ def g_container(arg):
return "container"
v = V()
- assert j(v) == "s"
+ assert g(v) == "s"
c.Container.register(V) # add c.Container to the virtual mro of V
- return j(v) # "s", since the virtual mro is V, Sized, S, Container
+ assert g(v) == "s" # since the virtual mro is V, Sized, S, Container
+ return g, V
+
if __name__ == '__main__':
import doctest
diff --git a/src/tests/test.py b/src/tests/test.py
index 1e1cb3f..951958c 100644
--- a/src/tests/test.py
+++ b/src/tests/test.py
@@ -36,7 +36,7 @@ class DocumentationTestCase(unittest.TestCase):
def test_singledispatch2(self):
if hasattr(functools, 'singledispatch'):
- self.assertEqual(doc.singledispatch_example2(), "s")
+ doc.singledispatch_example2()
class ExtraTestCase(unittest.TestCase):