I could see expanding to allow lists/sets as well as tuples being useful, e.g. for using dynamically generated prefix lists without creating additional tuple objects, but I don't see arbitrary iteration being necessary.<br>
<br><div>On Thu Jan 02 2014 at 3:25:20 PM, Guido van Rossum <<a href="mailto:guido@python.org">guido@python.org</a>> wrote:</div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
The current behavior is intentional, and the ambiguity of strings<br>
themselves being iterables is the main reason. Since startswith() is<br>
almost always called with a literal or tuple of literals anyway, I see<br>
little need to extend the semantics. (I notice that you don't actually<br>
give any examples where the iterator would be useful -- have you<br>
encountered any, or are you just arguing for consistency's sake?)<br>
<br>
On Thu, Jan 2, 2014 at 10:29 AM, James Powell <<a href="mailto:james@dontusethiscode.com" target="_blank">james@dontusethiscode.com</a>> wrote:<br>
> Some functions and methods allow the provision of a tuple of arguments<br>
> which will be looped over internally. e.g.,<br>
><br>
>     'spam'.startswith(('s', 'z')) # 'spam' starts with 's' or with 'z'<br>
>     isinstance(42, (float, int))<br>
><br>
> In these cases, CPython uses PyTuple_Check and PyTuple_GET_ITEM to<br>
> perform this internal iteration.<br>
><br>
> As a result, the following are considered invalid:<br>
><br>
>     'spam'.startswith(['s', 'z'])<br>
>     'spam'.startswith({'s', 'z'})<br>
>     'spam'.startswith(x for x in 'sz')<br>
><br>
>     Traceback (most recent call last):<br>
>       File "<stdin>", line 1, in <module><br>
>     TypeError: startswith first arg must be str, unicode, or tuple<br>
><br>
> There are two common workarounds:<br>
><br>
>     'spam'.startswith(tuple({'s', 'z'}))<br>
>     any('spam'.startwith(c) for c in {'s', 'z'})<br>
><br>
> Of course, the following construction already has a clear, separate meaning:<br>
><br>
>    'spam'.startswith('sz') # 'spam' starts with 'sz'<br>
><br>
> In these cases, could we supplant the PyTuple_Check with one that would<br>
> allow any iterator? Alternatively, could add this as an additional branch?<br>
><br>
> The code would look something like:<br>
><br>
>     it = PyObject_GetIter(subobj);<br>
>     if (it == NULL)<br>
>         return NULL;<br>
><br>
>     iternext = *Py_TYPE(it)->tp_iternext;<br>
>     for(;;) {<br>
>         substring = iternext(it);<br>
>         if (substring == NULL)<br>
>             Py_RETURN_FALSE;<br>
>         result = tailmatch(self, substring, start, end, -1);<br>
>         Py_DECREF(substring);<br>
>         if (result)<br>
>             Py_RETURN_TRUE;<br>
>     }<br>
><br>
> Of course, in the case of methods like .startswith, this would need to<br>
> ensure the following behaviour remains unchanged. The following should<br>
> always check if 'spam' starts with 'sz' not starts with 's' or with 'z':<br>
><br>
>     'spam'.startswith('sz')<br>
><br>
> I searched <a href="http://bugs.python.org" target="_blank">bugs.python.org</a> and python-ideas for any previous discussion<br>
> of this topic. If this seems reasonable, I can submit an enhancement to<br>
> <a href="http://bugs.python.org" target="_blank">bugs.python.org</a> with a patch for unicodeobject.c:unicode_<u></u>startswith<br>
><br>
> Cheers,<br>
> James Powell<br>
><br>
> follow: @dontusethiscode + @nycpython<br>
> attend: <a href="http://nycpython.org" target="_blank">nycpython.org</a> + <a href="http://flask-nyc.org" target="_blank">flask-nyc.org</a><br>
> read: <a href="http://seriously.dontusethiscode.com" target="_blank">seriously.dontusethiscode.com</a><br>
><br>
> ______________________________<u></u>_________________<br>
> Python-ideas mailing list<br>
> <a href="mailto:Python-ideas@python.org" target="_blank">Python-ideas@python.org</a><br>
> <a href="https://mail.python.org/mailman/listinfo/python-ideas" target="_blank">https://mail.python.org/<u></u>mailman/listinfo/python-ideas</a><br>
> Code of Conduct: <a href="http://python.org/psf/codeofconduct/" target="_blank">http://python.org/psf/<u></u>codeofconduct/</a><br>
<br>
<br>
<br>
--<br>
--Guido van Rossum (<a href="http://python.org/~guido" target="_blank">python.org/~guido</a>)<br>
______________________________<u></u>_________________<br>
Python-ideas mailing list<br>
<a href="mailto:Python-ideas@python.org" target="_blank">Python-ideas@python.org</a><br>
<a href="https://mail.python.org/mailman/listinfo/python-ideas" target="_blank">https://mail.python.org/<u></u>mailman/listinfo/python-ideas</a><br>
Code of Conduct: <a href="http://python.org/psf/codeofconduct/" target="_blank">http://python.org/psf/<u></u>codeofconduct/</a><br>
</blockquote>