[Python-checkins] bpo-24234: implement complex.__complex__ (GH-27887)

mdickinson webhook-mailer at python.org
Mon Aug 23 04:16:16 EDT 2021


https://github.com/python/cpython/commit/6082bb5addab93755ab6e2bd2ed6021b391e10d1
commit: 6082bb5addab93755ab6e2bd2ed6021b391e10d1
branch: main
author: Mark Dickinson <mdickinson at enthought.com>
committer: mdickinson <dickinsm at gmail.com>
date: 2021-08-23T09:15:49+01:00
summary:

bpo-24234: implement complex.__complex__ (GH-27887)

Co-authored-by: Dong-hee Na <donghee.na92 at gmail.com>

files:
A Misc/NEWS.d/next/Core and Builtins/2021-08-22-12-28-50.bpo-24234.n3oTdx.rst
M Lib/test/test_complex.py
M Lib/test/test_doctest.py
M Lib/test/test_typing.py
M Objects/clinic/complexobject.c.h
M Objects/complexobject.c

diff --git a/Lib/test/test_complex.py b/Lib/test/test_complex.py
index abd7e39cc5ae73..1cd025ed53a5d0 100644
--- a/Lib/test/test_complex.py
+++ b/Lib/test/test_complex.py
@@ -499,6 +499,18 @@ def __complex__(self):
             self.assertEqual(complex(complex1(1j)), 2j)
         self.assertRaises(TypeError, complex, complex2(1j))
 
+    def test___complex__(self):
+        z = 3 + 4j
+        self.assertEqual(z.__complex__(), z)
+        self.assertEqual(type(z.__complex__()), complex)
+
+        class complex_subclass(complex):
+            pass
+
+        z = complex_subclass(3 + 4j)
+        self.assertEqual(z.__complex__(), 3 + 4j)
+        self.assertEqual(type(z.__complex__()), complex)
+
     @support.requires_IEEE_754
     def test_constructor_special_numbers(self):
         class complex2(complex):
diff --git a/Lib/test/test_doctest.py b/Lib/test/test_doctest.py
index 8f761d7a52c23e..571dc78bf5076e 100644
--- a/Lib/test/test_doctest.py
+++ b/Lib/test/test_doctest.py
@@ -668,7 +668,7 @@ def non_Python_modules(): r"""
 
     >>> import builtins
     >>> tests = doctest.DocTestFinder().find(builtins)
-    >>> 816 < len(tests) < 836 # approximate number of objects with docstrings
+    >>> 820 < len(tests) < 840 # approximate number of objects with docstrings
     True
     >>> real_tests = [t for t in tests if len(t.examples) > 0]
     >>> len(real_tests) # objects that actually have doctests
diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py
index 3bd5894f425741..84521ee7dd95f5 100644
--- a/Lib/test/test_typing.py
+++ b/Lib/test/test_typing.py
@@ -1533,11 +1533,11 @@ def test_supports_float(self):
 
     def test_supports_complex(self):
 
-        # Note: complex itself doesn't have __complex__.
         class C:
             def __complex__(self):
                 return 0j
 
+        self.assertIsSubclass(complex, typing.SupportsComplex)
         self.assertIsSubclass(C, typing.SupportsComplex)
         self.assertNotIsSubclass(str, typing.SupportsComplex)
 
diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-08-22-12-28-50.bpo-24234.n3oTdx.rst b/Misc/NEWS.d/next/Core and Builtins/2021-08-22-12-28-50.bpo-24234.n3oTdx.rst
new file mode 100644
index 00000000000000..52397e90fbdfa1
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2021-08-22-12-28-50.bpo-24234.n3oTdx.rst	
@@ -0,0 +1,3 @@
+Implement the :meth:`__complex__` special method on the :class:`complex` type,
+so a complex number ``z`` passes an ``isinstance(z, typing.SupportsComplex)``
+check.
diff --git a/Objects/clinic/complexobject.c.h b/Objects/clinic/complexobject.c.h
index 557fbf9752faf7..e7d8065e874ef3 100644
--- a/Objects/clinic/complexobject.c.h
+++ b/Objects/clinic/complexobject.c.h
@@ -69,6 +69,24 @@ complex___format__(PyComplexObject *self, PyObject *arg)
     return return_value;
 }
 
+PyDoc_STRVAR(complex___complex____doc__,
+"__complex__($self, /)\n"
+"--\n"
+"\n"
+"Convert this value to exact type complex.");
+
+#define COMPLEX___COMPLEX___METHODDEF    \
+    {"__complex__", (PyCFunction)complex___complex__, METH_NOARGS, complex___complex____doc__},
+
+static PyObject *
+complex___complex___impl(PyComplexObject *self);
+
+static PyObject *
+complex___complex__(PyComplexObject *self, PyObject *Py_UNUSED(ignored))
+{
+    return complex___complex___impl(self);
+}
+
 PyDoc_STRVAR(complex_new__doc__,
 "complex(real=0, imag=0)\n"
 "--\n"
@@ -113,4 +131,4 @@ complex_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
 exit:
     return return_value;
 }
-/*[clinic end generated code: output=056cac3226d94967 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=6d85094ace15677e input=a9049054013a1b77]*/
diff --git a/Objects/complexobject.c b/Objects/complexobject.c
index 3e479497cfcc31..cfe6c737578a03 100644
--- a/Objects/complexobject.c
+++ b/Objects/complexobject.c
@@ -693,8 +693,29 @@ complex___format___impl(PyComplexObject *self, PyObject *format_spec)
     return _PyUnicodeWriter_Finish(&writer);
 }
 
+/*[clinic input]
+complex.__complex__
+
+Convert this value to exact type complex.
+[clinic start generated code]*/
+
+static PyObject *
+complex___complex___impl(PyComplexObject *self)
+/*[clinic end generated code: output=e6b35ba3d275dc9c input=3589ada9d27db854]*/
+{
+    if (PyComplex_CheckExact(self)) {
+        Py_INCREF(self);
+        return (PyObject *)self;
+    }
+    else {
+        return PyComplex_FromCComplex(self->cval);
+    }
+}
+
+
 static PyMethodDef complex_methods[] = {
     COMPLEX_CONJUGATE_METHODDEF
+    COMPLEX___COMPLEX___METHODDEF
     COMPLEX___GETNEWARGS___METHODDEF
     COMPLEX___FORMAT___METHODDEF
     {NULL,              NULL}           /* sentinel */



More information about the Python-checkins mailing list