【问题标题】:Python force dict entries to be utf-8Python 强制 dict 条目为 utf-8
【发布时间】:2012-05-25 19:54:31
【问题描述】:

我花了一个下午的大部分时间尝试将字典对象修补为 utf-8 编码来代替 unicode。我正在尝试找到最快和性能最好的方法来扩展字典对象并确保它的条目、键和值都是 utf-8。

这是我想出的,它可以完成工作,但我想知道可以进行哪些改进。

class UTF8Dict(dict):
    def __init__(self, *args, **kwargs):
        d = dict(*args, **kwargs)
        d = _decode_dict(d)
        super(UTF8Dict,self).__init__(d)
    def __setitem__(self,key,value):
        if isinstance(key,unicode):
            key = key.encode('utf-8')
        if isinstance(value,unicode):
            value = value.encode('utf-8')
        return super(UTF8Dict,self).__setitem__(key,value)

def _decode_list(data):
    rv = []
    for item in data:
        if isinstance(item, unicode):
            item = item.encode('utf-8')
        elif isinstance(item, list):
            item = _decode_list(item)
        elif isinstance(item, dict):
            item = _decode_dict(item)
        rv.append(item)
    return rv

def _decode_dict(data):
    rv = {}
    for key, value in data.iteritems():
        if isinstance(key, unicode):
            key = key.encode('utf-8')
        if isinstance(value, unicode):
            value = value.encode('utf-8')
        elif isinstance(value, list):
            value = _decode_list(value)
        elif isinstance(value, dict):
            value = _decode_dict(value)
        rv[key] = value
    return rv

改善以下任何一项的建议将非常有帮助:

  • 性能
  • 涵盖更多边缘情况
  • 错误处理

【问题讨论】:

  • 你为什么要这样做?只需将您的键/值存储为 unicode 对象,然后根据需要进行编码。在你的扩展中你最需要的是一个 isinstance 检查,如果它失败了就会引发一个异常。
  • 最佳实践是在代码的输入和输出边缘进行编码和解码(因此在收到时立即解码,在发送时尽可能晚地编码),并在内部保持 unicode。
  • 为什么要强制?只需制作一个字典并仅添加具有正确编码的键/值。尝试强制类型和编码不是 Pythonic。
  • “UTF-8 而不是 Unicode”。说什么?
  • @tchrist:Python 对“str”(字节字符串)和“unicode”(一系列 unicode 代码点)有不同的类型。 UTF-8 是 Unicode 的一种特殊编码;它指定字节字符串中的字节应该是什么。在 Python 解释器中自己尝试一下:s = u'résumé'; s; t = s.encode('utf8'); t;。 OP 需要字节字符串(以 UTF-8 编码),而不是 Unicode 字符串(与编码无关,无论是 UTF-8 还是 UTF-16 或其他)。

标签: python unicode utf-8 dictionary


【解决方案1】:

我同意 cmets 的说法,即这可能会被误导。也就是说,您当前的方案中有一些漏洞:

  1. d.setdefault 可用于将 unicode 对象添加到您的 dict:

    >>> d = UTF8Dict()
    >>> d.setdefault(u'x', u'y')
    
  2. d.update 可用于将 unicode 对象添加到您的 dict:

    >>> d = UTF8Dict()
    >>> d.update({u'x': u'y'})
    
  3. 可以使用任何标准列表操作修改包含在 dict 中的列表值以包含 unicode 对象。例如:

    >>> d = UTF8Dict(x=[])
    >>> d['x'].append(u'x')
    

为什么你要确保你的数据结构只包含 utf-8 字符串?

【讨论】:

  • 不知道。此连接到的端点仅处理 utf-8。他们的确切代码是if type(s) is str: hate_my_life(),所以这就是我修补所有这些的原因。我要求他们将其更改为isinstance(s,basestring),但“我们还没有准备好使用 unicode”还没有完全弄清楚那个。
  • @lukecampbell 编写一个以 dict 作为输入、遍历 dict(以及您关心的任何子结构)并编码任何 unicode 字符串的函数是否可行?然后,您可以在使用输入字典中需要 utf-8 的外部“端点”代码之前调用此函数。
  • 我最初是走那条路的,因此对象定义下的两个函数,但是从 dict 扩展的底层端点现在将扩展这个强制 utf-8 合规性的对象。我无法强制执行客户端在处理 dicts 时使用 utf-8 的策略。
  • 嗯.. 你能对正在执行if type(s) is str 的邪恶模块进行猴子补丁吗?例如,将type 函数注入到其名称空间中,类似于:if isinstance(s,basestring): return str; else: return __builtins__.type(s)?不完全干净,我承认。 :)
  • 我实际上只是将其更改为isinstance(s,basestring),但随后收到一封电子邮件,基本上说“不要碰它不在您的域中” 长电子邮件链跟着我试图推动 unicode 支持,这不是在 Python 中很难。
猜你喜欢
  • 2016-03-11
  • 2011-08-19
  • 2012-07-03
  • 1970-01-01
  • 1970-01-01
  • 2012-10-08
  • 1970-01-01
  • 2016-12-14
  • 1970-01-01
相关资源
最近更新 更多