python - 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))
并且文档 对我没有任何意义。
解决方案
简短的回答:不,它不等同。
最长的答案:
首先,Python2 没有“字节”类型——Python3bytes
是 Python2str
并且 Python3str
是 Python2 unicode
,所以正确的问题是:isinstance(X,Sequence)
等价于isinstance(X, (unicode, str))
.
那么,答案仍然是否定的。Py3str
和bytes
ARE 的实例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
现在,您的问题的真正答案可能会有所不同:“序列”是(或多或少)正式定义,并且存在调用您要移植的代码的上下文以及作者的意图。
作者可能假设他的函数只会传递列表、元组、字符串或字节,在这种情况下,测试意图确实是一种错误的(我什至会说是损坏的)和未记录的检查字符串和字节的尝试。
或者作者可能假设他的函数永远不会传递一个字符串或字节,但是我不明白为什么他会区别对待列表和元组与其他序列。
长话短说:您将不得不研究上下文,或者最终要求作者澄清 - 当然,如果可能的话。