Эквиваленты abc.Sequence в Python 2 - PullRequest
0 голосов
/ 03 июля 2018

Мне нужно преобразовать код 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))

и документация не имеет никакого смысла для меня.

1 Ответ

0 голосов
/ 03 июля 2018

Краткий ответ: нет, это не эквивалентно.

Самый длинный ответ:

Во-первых, Python2 не имеет типа "байты" - Python3 bytes - это Python2 str, а Python3 str - это Python2 unicode, поэтому правильный вопрос будет: isinstance(X,Sequence) эквивалентно isinstance(X, (unicode, str)).

Тогда ответом будет все еще нет. Py3 str и bytes ARE являются экземплярами abc.Sequence, действительно, , но , также как и любые экземпляры класса, реализующие abc.Sequence, так что вы можете иметь объекты, которые Sequence, не будучи str или bytes ((класс Джанго Queryset был бы идеальным кандидатом).

и этот документ: https://docs.python.org/3/library/collections.abc.html#collections.abc.Sequence не имеет никакого смысла для меня

Если вы перейдете по ссылке в этом документе, вы получите словесное определение того, что такое «последовательность»:

Итерация, которая поддерживает эффективный доступ к элементу с помощью целого числа индексы с помощью специального метода 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

Теперь реальный ответ на вашу проблему может быть немного другим: есть (более или менее) формальное определение того, что такое «последовательность», и есть контекст, в котором вызывается портируемый вами код, и автор намерение.

Автор мог предположить, что его функция будет когда-либо передаваться только списками, кортежами, строками или байтами, и в этом случае намерение теста действительно было ошибочным (я бы даже сказал, сломанным) и недокументированной попыткой проверить строки и байт.

Или автор мог предположить, что его функции просто никогда не будет передана строка или байты, но тогда я не могу понять, почему он будет обрабатывать списки и кортежи иначе, чем другие последовательности.

Короче говоря, вам придется изучить контекст или, в конце концов, попросить у автора разъяснений - если возможно, конечно.

...