[Python-ideas] Adding str.isascii() ?
Victor Stinner
victor.stinner at gmail.com
Wed Jan 31 08:44:02 EST 2018
I like the idea of str.isdigit(ascii=True): would behave as
str.isdigit() and str.isascii(). It's easy to implement and likely to
be very efficient. I'm just not sure that it's so commonly required?
At least, I guess that some users can be surprised that str.isdigit()
is "Unicode aware", accept non-ASCII digits, as int(str).
Victor
2018-01-31 12:18 GMT+01:00 INADA Naoki <songofacandy at gmail.com>:
> Hm, it seems I was too hurry to implement it...
>
>>
>> There were discussions about this. See for example
>> https://bugs.python.org/issue18814.
>>
>> In short, there are two considerations that prevented adding this feature:
>>
>> 1. This function can have the constant computation complexity in CPython
>> (just check a single bit), but other implementations may provide only the
>> linear computation complexity.
>>
>
> Yes. There are no O(1) guarantee about .isascii().
> But I expect UTF-8 based string implementation PyPy will have can achieve
> O(1); just test len(s) == __internal_utf8_len(s)
>
> I think if *some* of implementations can achieve O(1), it's beneficial
> to implement.
>
>
>> 2. In many cases just after taking the answer to this question we encode the
>> string to bytes (or decode bytes to string). Thus the most natural way to
>> determining if the string is ASCII-only is trying to encode it to ASCII.
>>
>
> Yes. But ASCII is so special.
> Someone may want to check ASCII before passing string to int(),
> float(), decimal.Decimal(), etc...
> But I don't think there is real use case for encodings other than ASCII.
>
>> And adding a new method to the basic type has a high bar.
>>
>
> Agree.
>
>> The code in ipaddress
>>
>> if not _BaseV4._DECIMAL_DIGITS.issuperset(prefixlen_str):
>> cls._report_invalid_netmask(prefixlen_str)
>> try:
>> prefixlen = int(prefixlen_str)
>> except ValueError:
>> cls._report_invalid_netmask(prefixlen_str)
>> if not (0 <= prefixlen <= cls._max_prefixlen):
>> cls._report_invalid_netmask(prefixlen_str)
>> return prefixlen
>>
>> can be rewritten as:
>>
>> if not prefixlen_str.isdigit():
>> cls._report_invalid_netmask(prefixlen_str)
>> try:
>> prefixlen = int(prefixlen_str.encode('ascii'))
>> except UnicodeEncodeError:
>> cls._report_invalid_netmask(prefixlen_str)
>> except ValueError:
>> cls._report_invalid_netmask(prefixlen_str)
>> if not (0 <= prefixlen <= cls._max_prefixlen):
>> cls._report_invalid_netmask(prefixlen_str)
>> return prefixlen
>>
>
> Yes. But .isascii() will be match faster than try ...
> .encode('ascii') ... except UnicodeEncodeError
> on most Python implementations.
>
>
>> Other possibility -- adding support of the boolean argument in str.isdigit()
>> and similar predicates that switch them to the ASCII-only mode. Such option
>> will be very useful for the str.strip(), str.split() and str.splilines()
>> methods. Currently they split using all Unicode whitespaces and line
>> separators, but there is a need to split only on ASCII whitespaces and line
>> separators CR, LF and CRLF. In case of str.strip() and str.split() you can
>> just pass the string of whitespace characters, but there is no such option
>> for str.splilines().
>>
>
> It sounds good idea. Maybe, keyword only argument `ascii=False`?
>
> But if revert adding str.isascii() from Python 3.7, same keyword-only
> argument should be
> added to int(), float(), decimal.Decimal(), fractions.Fraction(),
> etc... It's bit hard.
>
> So I think adding .isascii() is beneficial even if all str.is***()
> methods have `ascii=False` flag.
> _______________________________________________
> Python-ideas mailing list
> Python-ideas at python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
More information about the Python-ideas
mailing list