【问题标题】:Check if a character is Unicode in a way compatible with Python 2 and 3以与 Python 2 和 3 兼容的方式检查字符是否为 Unicode
【发布时间】:2018-09-14 13:58:45
【问题描述】:

EDIT:明确基于 cmets 允许的字符集

ASCII 字符集中允许的字符为a-zA-Z0-9-_./。不应允许 ASCII 集中的任何其他字符。

除了上面定义的不允许的 ASCII 集之外的 Unicode 字符也是允许的。

编辑结束

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

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

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

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

if isinstance(c, unicode)
    return True
if c not in VALID_CHARSET:
    return False

但是 Python-3 中的字符串默认是 Unicode,并且没有单独的 unicode 类型,所以这在那里不起作用。有什么更简洁的方法可以在两个 Python 版本中使用?

【问题讨论】:

  • “除了这些 Unicode 字符之外,也允许使用”——由于 Unicode 包含所有可能的字符,因此……相当广泛。
  • 考虑到 Unicode 包括所有 ASCII(在相同的代码点),我不清楚你想要完成什么。您想消除仅属于 ASCII 但不在白名单中的字符吗?
  • 我试图澄清一下
  • 最简单的方法可能是制作一个 forbidden 字符的set 用于测试,而不是 valid 字符(仅创建一组有效字符)以帮助构建无效集)。定义INVALID_CHARSET = frozenset(map(chr, range(128))) - VALID_CHARSET,然后您的is_valid_string 函数可以简化为return INVALID_CHARSET.isdisjoint(string)set/frozensetisdisjoint 方法是迄今为止检查禁止字符是否存在的最有效方法,因为它短路,不做临时,当值是内置类型时完全在 C 层运行)。
  • @ShadowRanger 谢谢!看起来它会起作用。如果问题是开放的,我会接受它。另外,感谢有关 isdisjoint 的提示,我不知道这一点。

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


【解决方案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 级别的函数,只需为绑定 @987654325 创建一个别名即可节省一点调用开销(以无法定义自己的文档字符串为代价) @方法:

is_valid_string = INVALID_CHARSET.isdisjoint

你不会比这更快; set/frozenset's isdisjoint method 将所有工作推到 C 层(每个字符没有字节码处理开销),短路(一旦看到无效字符,它立即返回),并在 ~O(1) 中执行每个查找(所以测试字符串长度为O(n))。

如果您不关心检查,而是想要去除无效字符,您可能想使用str.translate/unicode.translate 来批量删除无效字符,但是鉴于 API 在类型之间有所不同(Py3 str 和 Py2 unicode 使用一种形式,Py3 bytes 和 Py2 str 另一种形式),你必须费心让它在 Py2 和 Py3 上工作在同一个代码库上。

【讨论】:

  • 谢谢。非常感谢它在性能方面的提示。
猜你喜欢
  • 2012-07-03
  • 1970-01-01
  • 2016-04-04
  • 2014-03-18
  • 1970-01-01
  • 2012-05-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多