Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 553ee27

Browse filesBrowse files
authored
bpo-43682: Make staticmethod objects callable (GH-25117)
Static methods (@staticmethod) are now callable as regular functions.
1 parent 53114ff commit 553ee27
Copy full SHA for 553ee27

File tree

Expand file treeCollapse file tree

7 files changed

+32
-14
lines changed
Filter options
Expand file treeCollapse file tree

7 files changed

+32
-14
lines changed

‎Doc/library/functions.rst

Copy file name to clipboardExpand all lines: Doc/library/functions.rst
+10-5Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1619,8 +1619,9 @@ are always available. They are listed here in alphabetical order.
16191619
The ``@staticmethod`` form is a function :term:`decorator` -- see
16201620
:ref:`function` for details.
16211621

1622-
A static method can be called either on the class (such as ``C.f()``) or on an instance (such
1623-
as ``C().f()``).
1622+
A static method can be called either on the class (such as ``C.f()``) or on
1623+
an instance (such as ``C().f()``). Moreover, they can be called as regular
1624+
functions (such as ``f()``).
16241625

16251626
Static methods in Python are similar to those found in Java or C++. Also see
16261627
: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.
16321633
body and you want to avoid the automatic transformation to instance
16331634
method. For these cases, use this idiom::
16341635

1636+
def regular_function():
1637+
...
1638+
16351639
class C:
1636-
builtin_open = staticmethod(open)
1640+
method = staticmethod(regular_function)
16371641

16381642
For more information on static methods, see :ref:`types`.
16391643

16401644
.. versionchanged:: 3.10
16411645
Static methods now inherit the method attributes (``__module__``,
1642-
``__name__``, ``__qualname__``, ``__doc__`` and ``__annotations__``) and
1643-
have a new ``__wrapped__`` attribute.
1646+
``__name__``, ``__qualname__``, ``__doc__`` and ``__annotations__``),
1647+
have a new ``__wrapped__`` attribute, and are now callable as regular
1648+
functions.
16441649

16451650

16461651
.. index::

‎Doc/reference/datamodel.rst

Copy file name to clipboardExpand all lines: Doc/reference/datamodel.rst
+2-3Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1132,9 +1132,8 @@ Internal types
11321132
around any other object, usually a user-defined method object. When a static
11331133
method object is retrieved from a class or a class instance, the object actually
11341134
returned is the wrapped object, which is not subject to any further
1135-
transformation. Static method objects are not themselves callable, although the
1136-
objects they wrap usually are. Static method objects are created by the built-in
1137-
:func:`staticmethod` constructor.
1135+
transformation. Static method objects are also callable. Static method
1136+
objects are created by the built-in :func:`staticmethod` constructor.
11381137

11391138
Class method objects
11401139
A class method object, like a static method object, is a wrapper around another

‎Doc/whatsnew/3.10.rst

Copy file name to clipboardExpand all lines: Doc/whatsnew/3.10.rst
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,7 @@ Other Language Changes
623623
(:func:`@classmethod <classmethod>`) now inherit the method attributes
624624
(``__module__``, ``__name__``, ``__qualname__``, ``__doc__``,
625625
``__annotations__``) and have a new ``__wrapped__`` attribute.
626+
Moreover, static methods are now callable as regular functions.
626627
(Contributed by Victor Stinner in :issue:`43682`.)
627628
628629

‎Lib/test/test_decorators.py

Copy file name to clipboardExpand all lines: Lib/test/test_decorators.py
+8-4Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,14 +91,18 @@ def func(x):
9191
getattr(func, attr))
9292

9393
self.assertEqual(repr(wrapper), format_str.format(func))
94-
95-
self.assertRaises(TypeError, wrapper, 1)
94+
return wrapper
9695

9796
def test_staticmethod(self):
98-
self.check_wrapper_attrs(staticmethod, '<staticmethod({!r})>')
97+
wrapper = self.check_wrapper_attrs(staticmethod, '<staticmethod({!r})>')
98+
99+
# bpo-43682: Static methods are callable since Python 3.10
100+
self.assertEqual(wrapper(1), 1)
99101

100102
def test_classmethod(self):
101-
self.check_wrapper_attrs(classmethod, '<classmethod({!r})>')
103+
wrapper = self.check_wrapper_attrs(classmethod, '<classmethod({!r})>')
104+
105+
self.assertRaises(TypeError, wrapper, 1)
102106

103107
def test_dotted(self):
104108
decorators = MiscDecorators()

‎Lib/test/test_pydoc.py

Copy file name to clipboardExpand all lines: Lib/test/test_pydoc.py
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1142,7 +1142,7 @@ def sm(x, y):
11421142
'''A static method'''
11431143
...
11441144
self.assertEqual(self._get_summary_lines(X.__dict__['sm']),
1145-
'sm(...)\n'
1145+
'sm(x, y)\n'
11461146
' A static method\n')
11471147
self.assertEqual(self._get_summary_lines(X.sm), """\
11481148
sm(x, y)
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Static methods (:func:`@staticmethod <staticmethod>`) are now callable as
2+
regular functions. Patch by Victor Stinner.

‎Objects/funcobject.c

Copy file name to clipboardExpand all lines: Objects/funcobject.c
+8-1Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1040,6 +1040,13 @@ sm_init(PyObject *self, PyObject *args, PyObject *kwds)
10401040
return 0;
10411041
}
10421042

1043+
static PyObject*
1044+
sm_call(PyObject *callable, PyObject *args, PyObject *kwargs)
1045+
{
1046+
staticmethod *sm = (staticmethod *)callable;
1047+
return PyObject_Call(sm->sm_callable, args, kwargs);
1048+
}
1049+
10431050
static PyMemberDef sm_memberlist[] = {
10441051
{"__func__", T_OBJECT, offsetof(staticmethod, sm_callable), READONLY},
10451052
{"__wrapped__", T_OBJECT, offsetof(staticmethod, sm_callable), READONLY},
@@ -1107,7 +1114,7 @@ PyTypeObject PyStaticMethod_Type = {
11071114
0, /* tp_as_sequence */
11081115
0, /* tp_as_mapping */
11091116
0, /* tp_hash */
1110-
0, /* tp_call */
1117+
sm_call, /* tp_call */
11111118
0, /* tp_str */
11121119
0, /* tp_getattro */
11131120
0, /* tp_setattro */

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.