优化python编码功能

时间:2018-03-13 09:31:43

标签: python python-2.7 optimization

我写了一个函数,它将输入数据中的unicode编码转换为utf-8编码。

该函数能够处理原始string OR dict OR list作为输入,并返回相应的utf-8编码输出。

此功能是我正在开展的更大项目的一部分。此功能按预期提供正确的输出。

问题在于它在执行时间方面正成为我的瓶颈。虽然目前的执行时间已接近〜1ms,但正如我所说,它是更大项目的一部分,我必须重复调用此函数,这最终会损害我对API的响应时间

def fix_unicode(self, data):
    if isinstance(data, unicode):
        return data.encode('utf-8')
    elif isinstance(data, dict):
        data = dict((fix_unicode(k), fix_unicode(data[k])) for k in data)
    elif isinstance(data, list):
        for i in xrange(0, len(data)):
            data[i] = fix_unicode(data[i])
    return data

我可以进一步优化此功能吗?如果是的话怎么样?

2 个答案:

答案 0 :(得分:2)

您可以通过进行一些更改来提高执行速度:

  1. 仅检查type data而不是3次。这可以通过类似data_type = type(data)
  2. 的方式实现
  3. 使用词典理解是一个好主意。您可以通过直接调用字典理解来加快速度,而不是(a)设置生成器然后(b)调用dict函数。
  4. 使用python时尽可能避免递归。 Python没有任何形式的Tail Call Opitimsation。因此,从python程序(Stack Overflow)的角度来看,调用data = dict((fix_unicode(k), fix_unicode(data[k])) for k in data)是不安全的。
  5. 您可以使用更高阶函数map来避免手动迭代列表。
  6. 为实现上述目标,我们可以将功能分为两部分,以实现模块化和效率:

    def unicode_to_utf(self, string):
        """(unicode string) -> utf8_string"""
        return string.encode("utf-8")
    
    
    def fix_unicode(self, data):
        data_type = type(data)
        assert data_type in (unicode, dict, list),\
                "data must be either a unicode string, list or dictionary"
        fix = unicode_to_utf  # create a local copy of the function for faster lookup speed
        if data_type is unicode:
            return fix(data)
        elif data_type is dict:
            return {fix(k): fix(v) for k, v in data.iteritems()}
        else:
            return map(fix, data)
    

    如果您希望修改列表,可以将return map(fix, data)替换为理解[fix(datum) for datum in data]但是这样的函数行为将不一致,因为它返回字符串和dicts的新对象(尽管你可以同时修改dict),而它会修改列表。这对你来说是一种折衷。

    与此同时,您的代码应该运行得更快。

答案 1 :(得分:0)

虽然@ xero-smith答案非常好,但您想问一个问题:在调用函数之前,您确定不知道数据的类型吗? 通常,这种“重载”方法在更高级别使用,而不是用于可能成为bottelneck的方法。

我可以想象两种情况:

  1. 您是数据的制作者。那么你应该知道数据的类型,你的方法只是一个坏主意。在编译语言中,重载方法的选择是在编译时完成的,当你有三个fix_unicode方法时,没有惩罚,一个用于字符串,一个用于dicts,一个用于列表。但在这里,只需定义三种方法并选择正确的方法。
  2. 您只是数据的使用者。然后你应该尝试来了解数据的类型。这些数据来自哪里?一个JSON帖子?一个文本文件?在制作字典或列表之前,你不能转换它吗?您谈到了API:为什么不在查询字符串中使用参数?当然,您应该保留实际的API,但是添加一个可选的“提示参数”来加速您的项目。 (必须对此进行基准测试。)尽量避免在运行时检查数据类型。