summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2024-07-15 16:07:00 (GMT)
committerGitHub <noreply@github.com>2024-07-15 16:07:00 (GMT)
commit94bee45dee41876e88fe023b9163178d376355dc (patch)
treeedbd2ba0cf02984c04d7691fbdb54857652d0840 /Objects
parent8303d32ff55945c5b38eeeaf1b1811dbcf8aa9be (diff)
downloadcpython-94bee45dee41876e88fe023b9163178d376355dc.zip
cpython-94bee45dee41876e88fe023b9163178d376355dc.tar.gz
cpython-94bee45dee41876e88fe023b9163178d376355dc.tar.bz2
gh-84978: Add float.from_number() and complex.from_number() (GH-26827)
They are alternate constructors which only accept numbers (including objects with special methods __float__, __complex__ and __index__), but not strings.
Diffstat (limited to 'Objects')
-rw-r--r--Objects/clinic/complexobject.c.h11
-rw-r--r--Objects/clinic/floatobject.c.h11
-rw-r--r--Objects/complexobject.c62
-rw-r--r--Objects/floatobject.c31
4 files changed, 97 insertions, 18 deletions
diff --git a/Objects/clinic/complexobject.c.h b/Objects/clinic/complexobject.c.h
index 46c3b35..58fd4e2 100644
--- a/Objects/clinic/complexobject.c.h
+++ b/Objects/clinic/complexobject.c.h
@@ -160,4 +160,13 @@ skip_optional_pos:
exit:
return return_value;
}
-/*[clinic end generated code: output=295ecfd71389d7fe input=a9049054013a1b77]*/
+
+PyDoc_STRVAR(complex_from_number__doc__,
+"from_number($type, number, /)\n"
+"--\n"
+"\n"
+"Convert number to a complex floating-point number.");
+
+#define COMPLEX_FROM_NUMBER_METHODDEF \
+ {"from_number", (PyCFunction)complex_from_number, METH_O|METH_CLASS, complex_from_number__doc__},
+/*[clinic end generated code: output=188438cc9ae167f7 input=a9049054013a1b77]*/
diff --git a/Objects/clinic/floatobject.c.h b/Objects/clinic/floatobject.c.h
index 10f6149..d20b314 100644
--- a/Objects/clinic/floatobject.c.h
+++ b/Objects/clinic/floatobject.c.h
@@ -227,6 +227,15 @@ exit:
return return_value;
}
+PyDoc_STRVAR(float_from_number__doc__,
+"from_number($type, number, /)\n"
+"--\n"
+"\n"
+"Convert real number to a floating-point number.");
+
+#define FLOAT_FROM_NUMBER_METHODDEF \
+ {"from_number", (PyCFunction)float_from_number, METH_O|METH_CLASS, float_from_number__doc__},
+
PyDoc_STRVAR(float___getnewargs____doc__,
"__getnewargs__($self, /)\n"
"--\n"
@@ -318,4 +327,4 @@ float___format__(PyObject *self, PyObject *arg)
exit:
return return_value;
}
-/*[clinic end generated code: output=c79743c8551c30d9 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=b9c8a1b6759ca073 input=a9049054013a1b77]*/
diff --git a/Objects/complexobject.c b/Objects/complexobject.c
index 3189746..7c8a6bd 100644
--- a/Objects/complexobject.c
+++ b/Objects/complexobject.c
@@ -757,22 +757,6 @@ complex___complex___impl(PyComplexObject *self)
}
-static PyMethodDef complex_methods[] = {
- COMPLEX_CONJUGATE_METHODDEF
- COMPLEX___COMPLEX___METHODDEF
- COMPLEX___GETNEWARGS___METHODDEF
- COMPLEX___FORMAT___METHODDEF
- {NULL, NULL} /* sentinel */
-};
-
-static PyMemberDef complex_members[] = {
- {"real", Py_T_DOUBLE, offsetof(PyComplexObject, cval.real), Py_READONLY,
- "the real part of a complex number"},
- {"imag", Py_T_DOUBLE, offsetof(PyComplexObject, cval.imag), Py_READONLY,
- "the imaginary part of a complex number"},
- {0},
-};
-
static PyObject *
complex_from_string_inner(const char *s, Py_ssize_t len, void *type)
{
@@ -1142,6 +1126,52 @@ complex_new_impl(PyTypeObject *type, PyObject *r, PyObject *i)
return complex_subtype_from_doubles(type, cr.real, ci.real);
}
+/*[clinic input]
+@classmethod
+complex.from_number
+
+ number: object
+ /
+
+Convert number to a complex floating-point number.
+[clinic start generated code]*/
+
+static PyObject *
+complex_from_number(PyTypeObject *type, PyObject *number)
+/*[clinic end generated code: output=658a7a5fb0de074d input=3f8bdd3a2bc3facd]*/
+{
+ if (PyComplex_CheckExact(number) && type == &PyComplex_Type) {
+ Py_INCREF(number);
+ return number;
+ }
+ Py_complex cv = PyComplex_AsCComplex(number);
+ if (cv.real == -1.0 && PyErr_Occurred()) {
+ return NULL;
+ }
+ PyObject *result = PyComplex_FromCComplex(cv);
+ if (type != &PyComplex_Type && result != NULL) {
+ Py_SETREF(result, PyObject_CallOneArg((PyObject *)type, result));
+ }
+ return result;
+}
+
+static PyMethodDef complex_methods[] = {
+ COMPLEX_FROM_NUMBER_METHODDEF
+ COMPLEX_CONJUGATE_METHODDEF
+ COMPLEX___COMPLEX___METHODDEF
+ COMPLEX___GETNEWARGS___METHODDEF
+ COMPLEX___FORMAT___METHODDEF
+ {NULL, NULL} /* sentinel */
+};
+
+static PyMemberDef complex_members[] = {
+ {"real", Py_T_DOUBLE, offsetof(PyComplexObject, cval.real), Py_READONLY,
+ "the real part of a complex number"},
+ {"imag", Py_T_DOUBLE, offsetof(PyComplexObject, cval.imag), Py_READONLY,
+ "the imaginary part of a complex number"},
+ {0},
+};
+
static PyNumberMethods complex_as_number = {
(binaryfunc)complex_add, /* nb_add */
(binaryfunc)complex_sub, /* nb_subtract */
diff --git a/Objects/floatobject.c b/Objects/floatobject.c
index 31f4145..9e1ef2a 100644
--- a/Objects/floatobject.c
+++ b/Objects/floatobject.c
@@ -1670,6 +1670,36 @@ float_vectorcall(PyObject *type, PyObject * const*args,
/*[clinic input]
+@classmethod
+float.from_number
+
+ number: object
+ /
+
+Convert real number to a floating-point number.
+[clinic start generated code]*/
+
+static PyObject *
+float_from_number(PyTypeObject *type, PyObject *number)
+/*[clinic end generated code: output=bbcf05529fe907a3 input=1f8424d9bc11866a]*/
+{
+ if (PyFloat_CheckExact(number) && type == &PyFloat_Type) {
+ Py_INCREF(number);
+ return number;
+ }
+ double x = PyFloat_AsDouble(number);
+ if (x == -1.0 && PyErr_Occurred()) {
+ return NULL;
+ }
+ PyObject *result = PyFloat_FromDouble(x);
+ if (type != &PyFloat_Type && result != NULL) {
+ Py_SETREF(result, PyObject_CallOneArg((PyObject *)type, result));
+ }
+ return result;
+}
+
+
+/*[clinic input]
float.__getnewargs__
[clinic start generated code]*/
@@ -1782,6 +1812,7 @@ float___format___impl(PyObject *self, PyObject *format_spec)
}
static PyMethodDef float_methods[] = {
+ FLOAT_FROM_NUMBER_METHODDEF
FLOAT_CONJUGATE_METHODDEF
FLOAT___TRUNC___METHODDEF
FLOAT___FLOOR___METHODDEF