Python 2和3兼容的方式迭代通过dict与键和值

aps*_*nce 10 python dictionary python-2.x python-3.x

我有以下列表理解,仅适用于Python 2,因为使用iteritems():

foo = [key for key, value in some_dict.iteritems() if value['marked']]
Run Code Online (Sandbox Code Playgroud)

我无法导入任何库.是否有一种干净的方法可以兼容Python 2和3?

the*_*eye 13

你可以简单地dict.items()在Python 2和3中使用,

foo = [key for key, value in some_dict.items() if value['marked']]
Run Code Online (Sandbox Code Playgroud)

或者你可以简单地滚动你自己的items发电机版本,就像这样

def get_items(dict_object):
    for key in dict_object:
        yield key, dict_object[key]
Run Code Online (Sandbox Code Playgroud)

然后像这样使用它

for key, value in get_items({1: 2, 3: 4}):
    print key, value
Run Code Online (Sandbox Code Playgroud)


Dhi*_*aTN 10

我会说使用future模块比实现自己更好,很多东西已经以简约/优化的方式为你完成了:

from future.utils import viewitems

foo = [key for key, value in viewitems(some_dict) if value.get('marked')]
Run Code Online (Sandbox Code Playgroud)

如果你很好奇这viewitems()是如何工作的,它就像下面这样简单:

def viewitems(obj, **kwargs):
    """
    Function for iterating over dictionary items with the same set-like
    behaviour on Py2.7 as on Py3.

    Passes kwargs to method."""
    func = getattr(obj, "viewitems", None)
    if not func:
        func = obj.items
    return func(**kwargs)
Run Code Online (Sandbox Code Playgroud)

注意: 如果需要与2.7之前的Python版本兼容,那么你应该使用iteritems():

from future.utils import iteritems

foo = [key for key, value in iteritems(some_dict) if value.get('marked')]
Run Code Online (Sandbox Code Playgroud)


Mar*_*ers 6

最简单的方法是不关心仅通过使用创建的列表dict.items():

foo = [key for key, value in some_dict.items() if value['marked']]
Run Code Online (Sandbox Code Playgroud)

下一个选项是使用异常处理程序:

try:
    # Python 2
    iter_some_dict = some_dict.iteritems
except AttributeError:
    # Python 3
    iter_some_dict = some_dict.items

foo = [key for key, value in iter_some_dict if value['marked']]
Run Code Online (Sandbox Code Playgroud)

您使用的内容取决于some_dict获取的大小以及所有项目列表的创建是否会对性能和内存使用产生相当大的影响.您必须对确切的用例进行基准测试以确定这一点.