以与Python 2和3兼容的方式检查字符是否为Unicode

时间:2018-09-14 13:58:46

标签: python python-3.x python-2.7 unicode

编辑:根据注释澄清允许的字符集

ASCII字符集中允许的字符为a-zA-Z0-9-_.,{{1 }}。不允许使用ASCII集中的任何其他字符。

除了上面定义的不允许的ASCII集之外,还允许

Unicode字符。

编辑结束

我正在处理一些文本数据,其中仅允许使用ASCII字符为/a-zA-Z0-9-,{{1 }},_。除这些Unicode字符外,还允许使用。我需要确保传入的数据仅包含这些字符集。

检查允许的ASCII字符很容易:

.

但是我想知道除上述之外如何允许unicode字符。我想在Python-2.7中我可以像这样添加检查:

/

但是Python-3中的字符串默认情况下是Unicode,并且没有单独的from string import ascii_letters, digits VALID_CHARSET= set(ascii_letters + digits + "-_./") def is_valid_string(string): for c in string: if c not in VALID_CHARSET: return False return True 类型,因此在那儿不起作用。在这两个版本的Python中都可以使用的更干净的方法吗?

1 个答案:

答案 0 :(得分:1)

在我阅读问题时,您希望允许任何非ASCII字符,以及列入白名单的ASCII字符。由于制作一组所有有效字符是不切实际的(将有超过一百万个条目),因此最简单的解决方案是制作一组无效字符并验证您的字符串中是否不包含任何字符:

VALID_CHARSET = frozenset(ascii_letters + digits + "-_./")
INVALID_CHARSET = frozenset(map(chr, range(128))) - VALID_CHARSET

一旦有了,is_valid_string变得微不足道:

def is_valid_string(string):
    return INVALID_CHARSET.isdisjoint(string)

如果您愿意,甚至可以完全避免定义Python级别的函数,只需为绑定的{{起一个别名即可],从而节省了一些调用开销(以无法定义自己的文档字符串为代价)。 1}}方法:

isdisjoint

您将无法获得更快的速度; set/frozenset's isdisjoint method将所有工作推到C层(每个字符没有字节码处理开销),短路(一旦看到无效字符,立即返回),并在〜{{1}中执行每个查找}(因此测试字符串的长度为is_valid_string = INVALID_CHARSET.isdisjoint )。

如果您不关心检查,而是想删除无效字符,则可以使用O(1) / O(n)批量删除无效字符,但鉴于API在两种类型之间不同(Py3 str.translate和Py2 unicode.translate使用一种形式,Py3 str和Py2 unicode另一种形式),您必须麻烦使其在同一代码库的Py2和Py3上工作。