10000 Restify PEP 303 (#142) · python/peps@84de20b · GitHub
[go: up one dir, main page]

Skip to content
/ peps Public

Commit 84de20b

Browse files
Mariattaberkerpeksag
authored andcommitted
Restify PEP 303 (#142)
1 parent 61dcc6e commit 84de20b

File tree

1 file changed

+165
-147
lines changed

1 file changed

+165
-147
lines changed

pep-0303.txt

Lines changed: 165 additions & 147 deletions
Original file line numberDiff line numberDiff line change
@@ -5,192 +5,210 @@ Last-Modified: $Date$
55
Author: Thomas Bellman <bellman+pep-divmod@lysator.liu.se>
66
Status: Rejected
77
Type: Standards Track
8-
Content-Type: text/plain
8+
Content-Type: text/x-rst
99
Created: 31-Dec-2002
1010
Python-Version: 2.3
1111
Post-History:
1212

1313

1414
Abstract
15+
========
16+
17+
This PEP describes an extension to the built-in ``divmod()`` function,
18+
allowing it to take multiple divisors, chaining several calls to
19+
``divmod()`` into one.
1520

16-
This PEP describes an extension to the built-in divmod() function,
17-
allowing it to take multiple divisors, chaining several calls to
18-
divmod() into one.
1921

2022
Pronouncement
23+
=============
24+
25+
This PEP is rejected. Most uses for chained ``divmod()`` involve a
26+
constant modulus (in radix conversions for example) and are more
27+
properly coded as a loop. The example of splitting seconds
28+
into days/hours/minutes/seconds does not generalize to months
29+
and years; rather, the whole use case is handled more flexibly and
30+
robustly by date and time modules. The other use cases mentioned
31+
in the PEP are somewhat rare in real code. The proposal is also
32+
problematic in terms of clarity and obviousness. In the examples,
33+
it is not immediately clear that the argument order is correct or
34+
that the target tuple is of the right length. Users from other
35+
languages are more likely to understand the standard two argument
36+
form without having to re-read the documentation. See python-dev
37+
discussion on 17 June 2005 [1]_.
2138

22-
This PEP is rejected. Most uses for chained divmod() involve a
23-
constant modulus (in radix conversions for example) and are more
24 8000 -
properly coded as a loop. The example of splitting seconds
25-
into days/hours/minutes/seconds does not generalize to months
26-
and years; rather, the whole use case is handled more flexibly and
27-
robustly by date and time modules. The other use cases mentioned
28-
in the PEP are somewhat rare in real code. The proposal is also
29-
problematic in terms of clarity and obviousness. In the examples,
30-
it is not immediately clear that the argument order is correct or
31-
that the target tuple is of the right length. Users from other
32-
languages are more likely to understand the standard two argument
33-
form without having to re-read the documentation. See python-dev
34-
discussion on 17 June 2005.
3539

3640
Specification
37-
38-
The built-in divmod() function would be changed to accept multiple
39-
divisors, changing its signature from divmod(dividend, divisor) to
40-
divmod(dividend, *divisors). The dividend is divided by the last
41-
divisor, giving a quotient and a remainder. The quotient is then
42-
divided by the second to last divisor, giving a new quotient and
43-
remainder. This is repeated until all divisors have been used,
44-
and divmod() then returns a tuple consisting of the quotient from
45-
the last step, and the remainders from all the steps.
46-
47-
A Python implementation of the new divmod() behaviour could look
48-
like:
49-
50-
def divmod(dividend, *divisors):
51-
modulos = ()
52-
q = dividend
53-
while divisors:
54-
q,r = q.__divmod__(divisors[-1])
55-
modulos = (r,) + modulos
56-
divisors = divisors[:-1]
57-
return (q,) + modulos
41+
=============
42+
43+
The built-in ``divmod()`` function would be changed to accept multiple
44+
divisors, changing its signature from ``divmod(dividend, divisor)`` to
45+
``divmod(dividend, divisors)``. The dividend is divided by the last
46+
divisor, giving a quotient and a remainder. The quotient is then
47+
divided by the second to last divisor, giving a new quotient and
48+
remainder. This is repeated until all divisors have been used,
49+
and ``divmod()`` then returns a tuple consisting of the quotient from
50+
the last step, and the remainders from all the steps.
51+
52+
A Python implementation of the new ``divmod()`` behaviour could look
53+
like::
54+
55+
def divmod(dividend, *divisors):
56+
modulos = ()
57+
q = dividend
58+
while divisors:
59+
q, r = q.__divmod__(divisors[-1])
60+
modulos = (r,) + modulos
61+
divisors = divisors[:-1]
62+
return (q,) + modulos
5863

5964

6065
Motivation
66+
==========
6167

62-
Occasionally one wants to perform a chain of divmod() operations,
63-
calling divmod() on the quotient from the previous step, with
64-
varying divisors. The most common case is probably converting a
65-
number of seconds into weeks, days, hours, minutes and seconds.
66-
This would today be written as:
68+
Occasionally one wants to perform a chain of ``divmod()`` operations,
69+
calling ``divmod()`` on the quotient from the previous step, with
70+
varying divisors. The most common case is probably converting a
71+
number of seconds into weeks, days, hours, minutes and seconds.
72+
This would today be written as::
6773

68-
def secs_to_wdhms(seconds):
69-
m,s = divmod(seconds, 60)
70-
h,m = divmod(m, 60)
71-
d,h = divmod(h, 24)
72-
w,d = divmod(d, 7)
73-
return (w,d,h,m,s)
74+
def secs_to_wdhms(seconds):
75+
m, s = divmod(seconds, 60)
76+
h, m = divmod(m, 60)
77+
d, h = divmod(h, 24)
78+
w, d = divmod(d, 7)
79+
return (w, d, h, m, s)
7480

75-
This is tedious and easy to get wrong each time you need it.
81+
This is tedious and easy to get wrong each time you need it.
7682

77-
If instead the divmod() built-in is changed according the proposal,
78-
the code for converting seconds to weeks, days, hours, minutes and
79-
seconds then become
83+
If instead the ``divmod()`` built-in is changed according the proposal,
84+
the code for converting seconds to weeks, days, hours, minutes and
85+
seconds then become::
8086

81-
def secs_to_wdhms(seconds):
82-
w,d,h,m,s = divmod(seconds, 7, 24, 60, 60)
83-
return (w,d,h,m,s)
87+
def secs_to_wdhms(seconds):
88+
w, d, h, m, s = divmod(seconds, 7, 24, 60, 60)
89+
return (w, d, h, m, s)
8490

85-
which is easier to type, easier to type correctly, and easier to
86-
read.
91+
which is easier to type, easier to type correctly, and easier to
92+
read.
8793

88-
Other applications are:
94+
Other applications are:
8995

90-
- Astronomical angles (declination is measured in degrees, minutes
91-
and seconds, right ascension is measured in hours, minutes and
92-
seconds).
93-
- Old British currency (1 pound = 20 shilling, 1 shilling = 12 pence)
94-
- Anglo-Saxon length units: 1 mile = 1760 yards, 1 yard = 3 feet,
95-
1 foot = 12 inches.
96-
- Anglo-Saxon weight units: 1 long ton = 160 stone, 1 stone = 14
97-
pounds, 1 pound = 16 ounce, 1 ounce = 16 dram
98-
- British volumes: 1 gallon = 4 quart, 1 quart = 2 pint, 1 pint
99-
= 20 fluid ounces
96+
- Astronomical angles (declination is measured in degrees, minutes
97+
and seconds, right ascension is measured in hours, minutes and
98+
seconds).
99+
- Old British currency (1 pound = 20 shilling, 1 shilling = 12 pence)
100+
- Anglo-Saxon length units: 1 mile = 1760 yards, 1 yard = 3 feet,
101+
1 foot = 12 inches.
102+
- Anglo-Saxon weight units: 1 long ton = 160 stone, 1 stone = 14
103+
pounds, 1 pound = 16 ounce, 1 ounce = 16 dram
104+
- British volumes: 1 gallon = 4 quart, 1 quart = 2 pint, 1 pint
105+
= 20 fluid ounces
100106

101107

102108
Rationale
103-
104-
The idea comes from APL, which has an operator that does this. (I
105-
don't remember what the operator looks like, and it would probably
106-
be impossible to render in ASCII anyway.)
107-
108-
The APL operator takes a list as its second operand, while this
109-
PEP proposes that each divisor should be a separate argument to
110-
the divmod() function. This is mainly because it is expected that
111-
the most common uses will have the divisors as constants right in
112-
the call (as the 7, 24, 60, 60 above), and adding a set of
113-
parentheses or brackets would just clutter the call.
114-
115-
Requiring an explicit sequence as the second argument to divmod()
116-
would seriously break backwards compatibility. Making divmod()
117-
check its second argument for being a sequence is deemed to be too
118-
ugly to contemplate. And in the case where one *does* have a
119-
sequence that is computed other-where, it is easy enough to write
120-
divmod(x, *divs) instead.
121-
122-
Requiring at least one divisor, i.e rejecting divmod(x), has been
123-
considered, but no good reason to do so has come to mind, and is
124-
thus allowed in the name of generality.
125-
126-
Calling divmod() with no divisors should still return a tuple (of
127-
one element). Code that calls divmod() with a varying number of
128-
divisors, and thus gets a return value with an "unknown" number of
129-
elements, would otherwise have to special case that case. Code
130-
that *knows* it is calling divmod() with no divisors is considered
131-
to be too silly to warrant a special case.
132-
133-
Processing the divisors in the other direction, i.e dividing with
134-
the first divisor first, instead of dividing with the last divisor
135-
first, has been considered. However, the result comes with the
136-
most significant part first and the least significant part last
137-
(think of the chained divmod as a way of splitting a number into
138-
"digits", with varying weights), and it is reasonable to specify
139-
the divisors (weights) in the same order as the result.
140-
141-
The inverse operation:
142-
143-
def inverse_divmod(seq, *factors):
144-
product = seq[0]
145-
for x,y in zip(factors, seq[1:]):
146-
product = product * x + y
147-
return product
148-
149-
could also be useful. However, writing
150-
151-
seconds = (((((w * 7) + d) * 24 + h) * 60 + m) * 60 + s)
152-
153-
is less cumbersome both to write and to read than the chained
154-
divmods. It is therefore deemed to be less important, and its
155-
introduction can be deferred to its own PEP. Also, such a
156-
function needs a good name, and the PEP author has not managed to
157-
come up with one yet.
158-
159-
Calling divmod("spam") does not raise an error, despite strings
160-
supporting neither division nor modulo. However, unless we know
161-
the other object too, we can't determine whether divmod() would
162-
work or not, and thus it seems silly to forbid it.
109+
=========
110+
111+
The idea comes from APL, which has an operator that does this. (I
112+
don't remember what the operator looks like, and it would probably
113+
be impossible to render in ASCII anyway.)
114+
115+
The APL operator takes a list as its second operand, while this
116+
PEP proposes that each divisor should be a separate argument to
117+
the ``divmod()`` function. This is mainly because it is expected that
118+
the most common uses will have the divisors as constants right in
119+
the call (as the 7, 24, 60, 60 above), and adding a set of
120+
parentheses or brackets would just clutter the call.
121+
122+
Requiring an explicit sequence as the second argument to ``divmod()``
123+
would seriously break backwards compatibility. Making ``divmod()``
124+
check its second argument for being a sequence is deemed to be too
125+
ugly to contemplate. And in the case where one *does* have a
126+
sequence that is computed other-where, it is easy enough to write
127+
``divmod(x, *divs)`` instead.
128+
129+
Requiring at least one divisor, i.e rejecting ``divmod(x)``, has been
130+
considered, but no good reason to do so has come to mind, and is
131+
thus allowed in the name of generality.
132+
133+
Calling ``divmod()`` with no divisors should still return a tuple (of
134+
one element). Code that calls ``divmod()`` with a varying number of
135+
divisors, and thus gets a return value with an "unknown" number of
136+
elements, would otherwise have to special case that case. Code
137+
that *knows* it is calling ``divmod()`` with no divisors is considered
138+
to be too silly to warrant a special case.
139+
140+
Processing the divisors in the other direction, i.e dividing with
141+
the first divisor first, instead of dividing with the last divisor
142+
first, has been considered. However, the result comes with the
143+
most significant part first and the least significant part last
144+
(think of the chained divmod as a way of splitting a number into
145+
"digits", with varying weights), and it is reasonable to specify
146+
the divisors (weights) in the same order as the result.
147+
148+
The inverse operation::
149+
150+
def inverse_divmod(seq, *factors):
151+
product = seq[0]
152+
for x, y in zip(factors, seq[1:]):
153+
product = product * x + y
154+
return product
155+
156+
could also be useful. However, writing::
157+
158+
seconds = (((((w * 7) + d) * 24 + h) * 60 + m) * 60 + s)
159+
160+
is less cumbersome both to write and to read than the chained
161+
divmods. It is therefore deemed to be less important, and its
162+
introduction can be deferred to its own PEP. Also, such a
163+
function needs a good name, and the PEP author has not managed to
164+
come up with one yet.
165+
166+
Calling ``divmod("spam")`` does not raise an error, despite strings
167+
supporting neither division nor modulo. However, unless we know
168+
the other object too, we can't determine whether ``divmod()`` would
169+
work or not, and thus it seems silly to forbid it.
163170

164171

165172
Backwards Compatibility
173+
=======================
166174

167-
Any module that replaces the divmod() function in the __builtin__
168-
module, may cause other modules using the new syntax to break. It
169-
is expected that this is very uncommon.
175+
Any module that replaces the ``divmod()`` function in the ``__builtin__``
176+
module, may cause other modules using the new syntax to break. It
177+
is expected that this is very uncommon.
170178

171-
Code that expects a TypeError exception when calling divmod() with
172-
anything but two arguments will break. This is also expected to
173-
be very uncommon.
179+
Code that expects a ``TypeError`` exception when calling ``divmod()`` with
180+
anything but two arguments will break. This is also expected to
181+
be very uncommon.
174182

175-
No other issues regarding backwards compatibility are known.
183+
No other issues regarding backwards compatibility are known.
176184

177185

178186
Reference Implementation
187+
========================
179188

180-
Not finished yet, but it seems a rather straightforward
181-
new implementation of the function builtin_divmod() in
182-
Python/bltinmodule.c
189+
Not finished yet, but it seems a rather straightforward
190+
new implementation of the function ``builtin_divmod()`` in
191+
``Python/bltinmodule.c``.
192+
193+
194+
References
195+
==========
196+
197+
.. [1] Raymond Hettinger, "Propose rejection of PEP 303 -- Extend divmod() for
198+
Multiple Divisors" http://mail.python.org/pipermail/python-dev/2003-January/032492.html
183199

184200

185201
Copyright
202+
=========
203+
204+
This document has been placed in the public domain.
186205

187-
This document has been placed in the public domain.
188206

189207

190-
191-
Local Variables:
192-
mode: indented-text
193-
indent-tabs-mode: nil
194-
sentence-end-double-space: t
195-
fill-column: 70
196-
End:
208+
..
209+
Local Variables:
210+
mode: indented-text
211+
indent-tabs-mode: nil
212+
sentence-end-double-space: t
213+
fill-column: 70
214+
End:

0 commit comments

Comments
 (0)
0