Unverified Kaydet (Commit) e119b3d1 authored tarafından Raymond Hettinger's avatar Raymond Hettinger Kaydeden (comit) GitHub

bpo-37178: Allow a one argument form of math.perm() (GH-13905)

üst 8cc605ac
...@@ -210,7 +210,7 @@ Number-theoretic and representation functions ...@@ -210,7 +210,7 @@ Number-theoretic and representation functions
of *x* and are floats. of *x* and are floats.
.. function:: perm(n, k) .. function:: perm(n, k=None)
Return the number of ways to choose *k* items from *n* items Return the number of ways to choose *k* items from *n* items
without repetition and with order. without repetition and with order.
...@@ -218,6 +218,9 @@ Number-theoretic and representation functions ...@@ -218,6 +218,9 @@ Number-theoretic and representation functions
Evaluates to ``n! / (n - k)!`` when ``k <= n`` and evaluates Evaluates to ``n! / (n - k)!`` when ``k <= n`` and evaluates
to zero when ``k > n``. to zero when ``k > n``.
If *k* is not specified or is None, then *k* defaults to *n*
and the function returns ``n!``.
Raises :exc:`TypeError` if either of the arguments are not integers. Raises :exc:`TypeError` if either of the arguments are not integers.
Raises :exc:`ValueError` if either of the arguments are negative. Raises :exc:`ValueError` if either of the arguments are negative.
......
...@@ -1885,8 +1885,13 @@ class IsCloseTests(unittest.TestCase): ...@@ -1885,8 +1885,13 @@ class IsCloseTests(unittest.TestCase):
self.assertEqual(perm(n, 1), n) self.assertEqual(perm(n, 1), n)
self.assertEqual(perm(n, n), factorial(n)) self.assertEqual(perm(n, n), factorial(n))
# Test one argument form
for n in range(20):
self.assertEqual(perm(n), factorial(n))
self.assertEqual(perm(n, None), factorial(n))
# Raises TypeError if any argument is non-integer or argument count is # Raises TypeError if any argument is non-integer or argument count is
# not 2 # not 1 or 2
self.assertRaises(TypeError, perm, 10, 1.0) self.assertRaises(TypeError, perm, 10, 1.0)
self.assertRaises(TypeError, perm, 10, decimal.Decimal(1.0)) self.assertRaises(TypeError, perm, 10, decimal.Decimal(1.0))
self.assertRaises(TypeError, perm, 10, "1") self.assertRaises(TypeError, perm, 10, "1")
...@@ -1894,7 +1899,7 @@ class IsCloseTests(unittest.TestCase): ...@@ -1894,7 +1899,7 @@ class IsCloseTests(unittest.TestCase):
self.assertRaises(TypeError, perm, decimal.Decimal(10.0), 1) self.assertRaises(TypeError, perm, decimal.Decimal(10.0), 1)
self.assertRaises(TypeError, perm, "10", 1) self.assertRaises(TypeError, perm, "10", 1)
self.assertRaises(TypeError, perm, 10) self.assertRaises(TypeError, perm)
self.assertRaises(TypeError, perm, 10, 1, 3) self.assertRaises(TypeError, perm, 10, 1, 3)
self.assertRaises(TypeError, perm) self.assertRaises(TypeError, perm)
......
For math.perm(n, k), let k default to n, giving the same result as
factorial.
Give math.perm() a one argument form that means the same as
math.factorial().
...@@ -639,7 +639,7 @@ exit: ...@@ -639,7 +639,7 @@ exit:
} }
PyDoc_STRVAR(math_perm__doc__, PyDoc_STRVAR(math_perm__doc__,
"perm($module, n, k, /)\n" "perm($module, n, k=None, /)\n"
"--\n" "--\n"
"\n" "\n"
"Number of ways to choose k items from n items without repetition and with order.\n" "Number of ways to choose k items from n items without repetition and with order.\n"
...@@ -647,6 +647,9 @@ PyDoc_STRVAR(math_perm__doc__, ...@@ -647,6 +647,9 @@ PyDoc_STRVAR(math_perm__doc__,
"Evaluates to n! / (n - k)! when k <= n and evaluates\n" "Evaluates to n! / (n - k)! when k <= n and evaluates\n"
"to zero when k > n.\n" "to zero when k > n.\n"
"\n" "\n"
"If k is not specified or is None, then k defaults to n\n"
"and the function returns n!.\n"
"\n"
"Raises TypeError if either of the arguments are not integers.\n" "Raises TypeError if either of the arguments are not integers.\n"
"Raises ValueError if either of the arguments are negative."); "Raises ValueError if either of the arguments are negative.");
...@@ -661,13 +664,17 @@ math_perm(PyObject *module, PyObject *const *args, Py_ssize_t nargs) ...@@ -661,13 +664,17 @@ math_perm(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
{ {
PyObject *return_value = NULL; PyObject *return_value = NULL;
PyObject *n; PyObject *n;
PyObject *k; PyObject *k = Py_None;
if (!_PyArg_CheckPositional("perm", nargs, 2, 2)) { if (!_PyArg_CheckPositional("perm", nargs, 1, 2)) {
goto exit; goto exit;
} }
n = args[0]; n = args[0];
if (nargs < 2) {
goto skip_optional;
}
k = args[1]; k = args[1];
skip_optional:
return_value = math_perm_impl(module, n, k); return_value = math_perm_impl(module, n, k);
exit: exit:
...@@ -713,4 +720,4 @@ math_comb(PyObject *module, PyObject *const *args, Py_ssize_t nargs) ...@@ -713,4 +720,4 @@ math_comb(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
exit: exit:
return return_value; return return_value;
} }
/*[clinic end generated code: output=5004266613284dcc input=a9049054013a1b77]*/ /*[clinic end generated code: output=0eb1e76a769cdd30 input=a9049054013a1b77]*/
...@@ -3002,7 +3002,7 @@ math_prod_impl(PyObject *module, PyObject *iterable, PyObject *start) ...@@ -3002,7 +3002,7 @@ math_prod_impl(PyObject *module, PyObject *iterable, PyObject *start)
math.perm math.perm
n: object n: object
k: object k: object = None
/ /
Number of ways to choose k items from n items without repetition and with order. Number of ways to choose k items from n items without repetition and with order.
...@@ -3010,18 +3010,24 @@ Number of ways to choose k items from n items without repetition and with order. ...@@ -3010,18 +3010,24 @@ Number of ways to choose k items from n items without repetition and with order.
Evaluates to n! / (n - k)! when k <= n and evaluates Evaluates to n! / (n - k)! when k <= n and evaluates
to zero when k > n. to zero when k > n.
If k is not specified or is None, then k defaults to n
and the function returns n!.
Raises TypeError if either of the arguments are not integers. Raises TypeError if either of the arguments are not integers.
Raises ValueError if either of the arguments are negative. Raises ValueError if either of the arguments are negative.
[clinic start generated code]*/ [clinic start generated code]*/
static PyObject * static PyObject *
math_perm_impl(PyObject *module, PyObject *n, PyObject *k) math_perm_impl(PyObject *module, PyObject *n, PyObject *k)
/*[clinic end generated code: output=e021a25469653e23 input=b2e7729d9a1949cf]*/ /*[clinic end generated code: output=e021a25469653e23 input=5311c5a00f359b53]*/
{ {
PyObject *result = NULL, *factor = NULL; PyObject *result = NULL, *factor = NULL;
int overflow, cmp; int overflow, cmp;
long long i, factors; long long i, factors;
if (k == Py_None) {
return math_factorial(module, n);
}
n = PyNumber_Index(n); n = PyNumber_Index(n);
if (n == NULL) { if (n == NULL) {
return NULL; return NULL;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment