Movatterモバイル変換


[0]ホーム

URL:


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

Sign up
Appearance settings

Commit444156e

Browse files
gh-117431: Adapt str.startswith and str.endswith to Argument Clinic (#117466)
This change gives a significant speedup, as the METH_FASTCALL callingconvention is now used.
1 parent65524ab commit444156e

File tree

4 files changed

+149
-49
lines changed

4 files changed

+149
-49
lines changed

‎Lib/test/string_tests.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1513,9 +1513,9 @@ def test_find_etc_raise_correct_error_messages(self):
15131513
x,None,None,None)
15141514
self.assertRaisesRegex(TypeError,r'^count\(',s.count,
15151515
x,None,None,None)
1516-
self.assertRaisesRegex(TypeError,r'^startswith\(',s.startswith,
1516+
self.assertRaisesRegex(TypeError,r'^startswith\b',s.startswith,
15171517
x,None,None,None)
1518-
self.assertRaisesRegex(TypeError,r'^endswith\(',s.endswith,
1518+
self.assertRaisesRegex(TypeError,r'^endswith\b',s.endswith,
15191519
x,None,None,None)
15201520

15211521
# issue #15534
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Improve the performance of:meth:`str.startswith` and:meth:`str.endswith`
2+
by adapting them to the:c:macro:`METH_FASTCALL` calling convention.

‎Objects/clinic/unicodeobject.c.h‎

Lines changed: 103 additions & 1 deletion
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎Objects/unicodeobject.c‎

Lines changed: 42 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -13021,40 +13021,41 @@ unicode_zfill_impl(PyObject *self, Py_ssize_t width)
1302113021
returnu;
1302213022
}
1302313023

13024-
PyDoc_STRVAR(startswith__doc__,
13025-
"S.startswith(prefix[, start[, end]]) -> bool\n\
13026-
\n\
13027-
Return True if S starts with the specified prefix, False otherwise.\n\
13028-
With optional start, test S beginning at that position.\n\
13029-
With optional end, stop comparing S at that position.\n\
13030-
prefix can also be a tuple of strings to try.");
13024+
/*[clinic input]
13025+
@text_signature "($self, prefix[, start[, end]], /)"
13026+
str.startswith as unicode_startswith
13027+
13028+
prefix as subobj: object
13029+
A string or a tuple of strings to try.
13030+
start: slice_index(accept={int, NoneType}, c_default='0') = None
13031+
Optional start position. Default: start of the string.
13032+
end: slice_index(accept={int, NoneType}, c_default='PY_SSIZE_T_MAX') = None
13033+
Optional stop position. Default: end of the string.
13034+
/
13035+
13036+
Return True if the string starts with the specified prefix, False otherwise.
13037+
[clinic start generated code]*/
1303113038

1303213039
staticPyObject*
13033-
unicode_startswith(PyObject*self,
13034-
PyObject*args)
13040+
unicode_startswith_impl(PyObject*self,PyObject*subobj,Py_ssize_tstart,
13041+
Py_ssize_tend)
13042+
/*[clinic end generated code: output=4bd7cfd0803051d4 input=5f918b5f5f89d856]*/
1303513043
{
13036-
PyObject*subobj;
13037-
PyObject*substring;
13038-
Py_ssize_tstart=0;
13039-
Py_ssize_tend=PY_SSIZE_T_MAX;
13040-
intresult;
13041-
13042-
if (!asciilib_parse_args_finds("startswith",args,&subobj,&start,&end))
13043-
returnNULL;
1304413044
if (PyTuple_Check(subobj)) {
1304513045
Py_ssize_ti;
1304613046
for (i=0;i<PyTuple_GET_SIZE(subobj);i++) {
13047-
substring=PyTuple_GET_ITEM(subobj,i);
13047+
PyObject*substring=PyTuple_GET_ITEM(subobj,i);
1304813048
if (!PyUnicode_Check(substring)) {
1304913049
PyErr_Format(PyExc_TypeError,
1305013050
"tuple for startswith must only contain str, "
1305113051
"not %.100s",
1305213052
Py_TYPE(substring)->tp_name);
1305313053
returnNULL;
1305413054
}
13055-
result=tailmatch(self,substring,start,end,-1);
13056-
if (result==-1)
13055+
intresult=tailmatch(self,substring,start,end,-1);
13056+
if (result<0) {
1305713057
returnNULL;
13058+
}
1305813059
if (result) {
1305913060
Py_RETURN_TRUE;
1306013061
}
@@ -13068,47 +13069,41 @@ unicode_startswith(PyObject *self,
1306813069
"a tuple of str, not %.100s",Py_TYPE(subobj)->tp_name);
1306913070
returnNULL;
1307013071
}
13071-
result=tailmatch(self,subobj,start,end,-1);
13072-
if (result==-1)
13072+
intresult=tailmatch(self,subobj,start,end,-1);
13073+
if (result<0) {
1307313074
returnNULL;
13075+
}
1307413076
returnPyBool_FromLong(result);
1307513077
}
1307613078

1307713079

13078-
PyDoc_STRVAR(endswith__doc__,
13079-
"S.endswith(suffix[, start[, end]]) -> bool\n\
13080-
\n\
13081-
Return True if S ends with the specified suffix, False otherwise.\n\
13082-
With optional start, test S beginning at that position.\n\
13083-
With optional end, stop comparing S at that position.\n\
13084-
suffix can also be a tuple of strings to try.");
13080+
/*[clinic input]
13081+
@text_signature "($self, prefix[, start[, end]], /)"
13082+
str.endswith as unicode_endswith = str.startswith
13083+
13084+
Return True if the string ends with the specified prefix, False otherwise.
13085+
[clinic start generated code]*/
1308513086

1308613087
staticPyObject*
13087-
unicode_endswith(PyObject*self,
13088-
PyObject*args)
13088+
unicode_endswith_impl(PyObject*self,PyObject*subobj,Py_ssize_tstart,
13089+
Py_ssize_tend)
13090+
/*[clinic end generated code: output=cce6f8ceb0102ca9 input=82cd5ce9e7623646]*/
1308913091
{
13090-
PyObject*subobj;
13091-
PyObject*substring;
13092-
Py_ssize_tstart=0;
13093-
Py_ssize_tend=PY_SSIZE_T_MAX;
13094-
intresult;
13095-
13096-
if (!asciilib_parse_args_finds("endswith",args,&subobj,&start,&end))
13097-
returnNULL;
1309813092
if (PyTuple_Check(subobj)) {
1309913093
Py_ssize_ti;
1310013094
for (i=0;i<PyTuple_GET_SIZE(subobj);i++) {
13101-
substring=PyTuple_GET_ITEM(subobj,i);
13095+
PyObject*substring=PyTuple_GET_ITEM(subobj,i);
1310213096
if (!PyUnicode_Check(substring)) {
1310313097
PyErr_Format(PyExc_TypeError,
1310413098
"tuple for endswith must only contain str, "
1310513099
"not %.100s",
1310613100
Py_TYPE(substring)->tp_name);
1310713101
returnNULL;
1310813102
}
13109-
result=tailmatch(self,substring,start,end,+1);
13110-
if (result==-1)
13103+
intresult=tailmatch(self,substring,start,end,+1);
13104+
if (result<0) {
1311113105
returnNULL;
13106+
}
1311213107
if (result) {
1311313108
Py_RETURN_TRUE;
1311413109
}
@@ -13121,9 +13116,10 @@ unicode_endswith(PyObject *self,
1312113116
"a tuple of str, not %.100s",Py_TYPE(subobj)->tp_name);
1312213117
returnNULL;
1312313118
}
13124-
result=tailmatch(self,subobj,start,end,+1);
13125-
if (result==-1)
13119+
intresult=tailmatch(self,subobj,start,end,+1);
13120+
if (result<0) {
1312613121
returnNULL;
13122+
}
1312713123
returnPyBool_FromLong(result);
1312813124
}
1312913125

@@ -13576,8 +13572,8 @@ static PyMethodDef unicode_methods[] = {
1357613572
UNICODE_SWAPCASE_METHODDEF
1357713573
UNICODE_TRANSLATE_METHODDEF
1357813574
UNICODE_UPPER_METHODDEF
13579-
{"startswith", (PyCFunction)unicode_startswith,METH_VARARGS,startswith__doc__},
13580-
{"endswith", (PyCFunction)unicode_endswith,METH_VARARGS,endswith__doc__},
13575+
UNICODE_STARTSWITH_METHODDEF
13576+
UNICODE_ENDSWITH_METHODDEF
1358113577
UNICODE_REMOVEPREFIX_METHODDEF
1358213578
UNICODE_REMOVESUFFIX_METHODDEF
1358313579
UNICODE_ISASCII_METHODDEF

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp