The equivalents of abc.Sequence in Python 2


The equivalents of abc.Sequence in Python 2



I need to convert to some Python 3 code to Python 2 code


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)



as you can see above, I want to know whether:


isinstance(X,Sequence)



equals to


isinstance(X,(str,bytes))



and the documentation
does not make any sense to me.




1 Answer
1



Short answer: no, it's not equivalent.



Longest answer:



First, Python2 has no "bytes" type - Python3 bytes are Python2 str and Python3 str is Python2 unicode, so the right question would be: is isinstance(X,Sequence) equivalent to isinstance(X, (unicode, str)).


bytes


str


str


unicode


isinstance(X,Sequence)


isinstance(X, (unicode, str))



Then, the answer is still no. Py3 str and bytes ARE instances of abc.Sequence indeed, but so are any instances of a class implementing abc.Sequence, so you can have objects that are Sequence without being str or bytes ((Django orm's Queryset class would be a perfect candidate).


str


bytes


abc.Sequence


abc.Sequence


Sequence


str


bytes


Queryset



and this doc: https://docs.python.org/3/library/collections.abc.html#collections.abc.Sequence make not no sense to me



If you follow the link in this doc, you get a verbal definition of what a "sequence" is:



An iterable which supports efficient element access using integer
indices via the getitem() special method and defines a len()
method that returns the length of the sequence
(..)
Note that dict also supports getitem() and len(), but is considered a mapping rather than a sequence



According to this definition, to test if an object is a sequence, you have to test whether it's iterable, have a __getitem__ and a __len_ method and is not a dict. This won't be an exact equivalent of the py3 code, but it's the closer you can get (at least without more context, cf below):


__getitem__


__len_


dict


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



Now the real answer to your problem might be a bit different: there's the (more or les) formal definition of what a "sequence" is, and there's the context in which the code you're porting is called and the author's intent.



The author might have assumed that his function would only ever be passed lists, tuples, strings or bytes, in which case the test intent was indeed a misguided (I'd even say broken) and undocumented attempt to check for strings and bytes.



Or the author might have assumed that his function would just never be passed a string or bytes, but then I can't understand why he would treat lists and tuples differently from other sequences.



To make a long story short: you will have to study the context, or eventually ask the author for clarification - if possible, of course.






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

api-platform.com Unable to generate an IRI for the item of type

How to set up datasource with Spring for HikariCP?

Display dokan vendor name on Woocommerce single product pages