首页 > 解决方案 > Python 2 中 abc.Sequence 的等价物

问题描述

我需要将一些 Python 3 代码转换为 Python 2 代码

from collections.abc import Sequence

def to_tensor(X, device):
  .....
    if isinstance(X, (list, tuple)):
        return [to_tensor_(x) for x in X]

    if isinstance(X,Sequence):<-------equals to if isinstance(X,(str,bytes))?
        X = torch.tensor(np.array(X))

    return X.to(device)

如您在上面看到的,我想知道是否:

isinstance(X,Sequence)

等于

isinstance(X,(str,bytes))

并且文档 对我没有任何意义。

标签: pythonpython-3.xpython-2.7code-conversion

解决方案


简短的回答:不,它不等同。

最长的答案:

首先,Python2 没有“字节”类型——Python3bytes是 Python2str并且 Python3str是 Python2 unicode,所以正确的问题是:isinstance(X,Sequence)等价于isinstance(X, (unicode, str)).

那么,答案仍然是否定的。Py3strbytesARE 的实例abc.Sequence确实如此,实现的类的任何实例也是abc.Sequence如此,因此您可以拥有Sequence不存在str或的对象bytes((Django orm 的Queryset类将是一个完美的候选者)。

这个文档:https://docs.python.org/3/library/collections.abc.html#collections.abc.Sequence对我来说没有意义

如果您点击此文档中的链接,您将获得“序列”的口头定义:

一个 iterable,它支持通过getitem () 特殊方法使用整数索引进行有效的元素访问,并定义了一个len () 方法,该方法返回序列的长度 (..) 请注意,dict 还支持getitem () 和len (),但是考虑映射而不是序列

根据这个定义,要测试一个对象是否是一个序列,你必须测试它是否是可迭代的,是否有一个__getitem__和一个__len_方法而不是一个dict。这不会完全等同于 py3 代码,但它是你可以得到的更接近的(至少没有更多上下文,参见下面):

def is_sequence(obj):
    if isinstance(obj, dict):
        return False

    if not (
        hasattr(obj, "__getitem__") 
        and hasattr(obj, "__len__")
        ): 
        return False

    # we might have false postive here
    # with dict-likes not inheriting from
    # `dict`, so we also weed out objects 
    # having a `keys()` methods which
    # are most likely dict-likes
    if hasattr(obj, "keys"):
        return False
    return True

现在,您的问题的真正答案可能会有所不同:“序列”是(或多或少)正式定义,并且存在调用您要移植的代码的上下文以及作者的意图。

作者可能假设他的函数只会传递列表、元组、字符串或字节,在这种情况下,测试意图确实是一种错误的(我什至会说是损坏的)和未记录的检查字符串和字节的尝试。

或者作者可能假设他的函数永远不会传递一个字符串或字节,但是我不明白为什么他会区别对待列表和元组与其他序列。

长话短说:您将不得不研究上下文,或者最终要求作者澄清 - 当然,如果可能的话。


推荐阅读