mirror of
https://github.com/python/cpython.git
synced 2025-09-26 10:19:53 +00:00
bpo-43682: Make staticmethod objects callable (GH-25117)
Static methods (@staticmethod) are now callable as regular functions.
This commit is contained in:
parent
53114ffef1
commit
553ee2781a
7 changed files with 32 additions and 14 deletions
|
@ -1619,8 +1619,9 @@ are always available. They are listed here in alphabetical order.
|
|||
The ``@staticmethod`` form is a function :term:`decorator` -- see
|
||||
:ref:`function` for details.
|
||||
|
||||
A static method can be called either on the class (such as ``C.f()``) or on an instance (such
|
||||
as ``C().f()``).
|
||||
A static method can be called either on the class (such as ``C.f()``) or on
|
||||
an instance (such as ``C().f()``). Moreover, they can be called as regular
|
||||
functions (such as ``f()``).
|
||||
|
||||
Static methods in Python are similar to those found in Java or C++. Also see
|
||||
:func:`classmethod` for a variant that is useful for creating alternate class
|
||||
|
@ -1632,15 +1633,19 @@ are always available. They are listed here in alphabetical order.
|
|||
body and you want to avoid the automatic transformation to instance
|
||||
method. For these cases, use this idiom::
|
||||
|
||||
def regular_function():
|
||||
...
|
||||
|
||||
class C:
|
||||
builtin_open = staticmethod(open)
|
||||
method = staticmethod(regular_function)
|
||||
|
||||
For more information on static methods, see :ref:`types`.
|
||||
|
||||
.. versionchanged:: 3.10
|
||||
Static methods now inherit the method attributes (``__module__``,
|
||||
``__name__``, ``__qualname__``, ``__doc__`` and ``__annotations__``) and
|
||||
have a new ``__wrapped__`` attribute.
|
||||
``__name__``, ``__qualname__``, ``__doc__`` and ``__annotations__``),
|
||||
have a new ``__wrapped__`` attribute, and are now callable as regular
|
||||
functions.
|
||||
|
||||
|
||||
.. index::
|
||||
|
|
|
@ -1132,9 +1132,8 @@ Internal types
|
|||
around any other object, usually a user-defined method object. When a static
|
||||
method object is retrieved from a class or a class instance, the object actually
|
||||
returned is the wrapped object, which is not subject to any further
|
||||
transformation. Static method objects are not themselves callable, although the
|
||||
objects they wrap usually are. Static method objects are created by the built-in
|
||||
:func:`staticmethod` constructor.
|
||||
transformation. Static method objects are also callable. Static method
|
||||
objects are created by the built-in :func:`staticmethod` constructor.
|
||||
|
||||
Class method objects
|
||||
A class method object, like a static method object, is a wrapper around another
|
||||
|
|
|
@ -623,6 +623,7 @@ Other Language Changes
|
|||
(:func:`@classmethod <classmethod>`) now inherit the method attributes
|
||||
(``__module__``, ``__name__``, ``__qualname__``, ``__doc__``,
|
||||
``__annotations__``) and have a new ``__wrapped__`` attribute.
|
||||
Moreover, static methods are now callable as regular functions.
|
||||
(Contributed by Victor Stinner in :issue:`43682`.)
|
||||
|
||||
|
||||
|
|
|
@ -91,14 +91,18 @@ class TestDecorators(unittest.TestCase):
|
|||
getattr(func, attr))
|
||||
|
||||
self.assertEqual(repr(wrapper), format_str.format(func))
|
||||
|
||||
self.assertRaises(TypeError, wrapper, 1)
|
||||
return wrapper
|
||||
|
||||
def test_staticmethod(self):
|
||||
self.check_wrapper_attrs(staticmethod, '<staticmethod({!r})>')
|
||||
wrapper = self.check_wrapper_attrs(staticmethod, '<staticmethod({!r})>')
|
||||
|
||||
# bpo-43682: Static methods are callable since Python 3.10
|
||||
self.assertEqual(wrapper(1), 1)
|
||||
|
||||
def test_classmethod(self):
|
||||
self.check_wrapper_attrs(classmethod, '<classmethod({!r})>')
|
||||
wrapper = self.check_wrapper_attrs(classmethod, '<classmethod({!r})>')
|
||||
|
||||
self.assertRaises(TypeError, wrapper, 1)
|
||||
|
||||
def test_dotted(self):
|
||||
decorators = MiscDecorators()
|
||||
|
|
|
@ -1142,7 +1142,7 @@ class TestDescriptions(unittest.TestCase):
|
|||
'''A static method'''
|
||||
...
|
||||
self.assertEqual(self._get_summary_lines(X.__dict__['sm']),
|
||||
'sm(...)\n'
|
||||
'sm(x, y)\n'
|
||||
' A static method\n')
|
||||
self.assertEqual(self._get_summary_lines(X.sm), """\
|
||||
sm(x, y)
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
Static methods (:func:`@staticmethod <staticmethod>`) are now callable as
|
||||
regular functions. Patch by Victor Stinner.
|
|
@ -1040,6 +1040,13 @@ sm_init(PyObject *self, PyObject *args, PyObject *kwds)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
sm_call(PyObject *callable, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
staticmethod *sm = (staticmethod *)callable;
|
||||
return PyObject_Call(sm->sm_callable, args, kwargs);
|
||||
}
|
||||
|
||||
static PyMemberDef sm_memberlist[] = {
|
||||
{"__func__", T_OBJECT, offsetof(staticmethod, sm_callable), READONLY},
|
||||
{"__wrapped__", T_OBJECT, offsetof(staticmethod, sm_callable), READONLY},
|
||||
|
@ -1107,7 +1114,7 @@ PyTypeObject PyStaticMethod_Type = {
|
|||
0, /* tp_as_sequence */
|
||||
0, /* tp_as_mapping */
|
||||
0, /* tp_hash */
|
||||
0, /* tp_call */
|
||||
sm_call, /* tp_call */
|
||||
0, /* tp_str */
|
||||
0, /* tp_getattro */
|
||||
0, /* tp_setattro */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue