Re: operator module isSequenceType with builtin set produces False

2 views
Skip to first unread message

Gabriel Genellina

unread,
Dec 18, 2007, 11:24:07 PM12/18/07
to pytho...@python.org
En Tue, 18 Dec 2007 09:15:12 -0300, English, Mark <Mark.E...@rbccm.com>
escribió:

>>>> try: set
>>>> except NameError: from sets import Set as set
>>>> class myset_fails(set): pass
>>>> class myset_works(set):
>>>> def __getitem__(self): pass
>>>> s = set()
>>>> fails = myset_fails()
>>>> works = myset_works()
>>>> import operator
>>>> operator.isSequenceType(s) #Not what I expected
> False
>>>> operator.isSequenceType(fails) #Not what I expected either
> False
>>>> operator.isSequenceType(works) #A hint at what isSequenceType does ?
> True
>
> Are sets not sequences ? I didn't think the isSequenceDisclaimer gave
> false negatives.

No, sets aren't sequences, as they have no order. Same as dicts, which
aren't sequences either.
If you add a __getitem__ method, isSequenceType can only *guess* that it
*could* be used with integer indexes, so this object *could* be (or behave
like) a sequence. The object could be a mapping too, and there is no way
to tell the difference without inspecting or executing __getitem__. That's
all isSequenceType can do for arbitrary objects.

> See Raymond Hettinger's post here too:
> http://groups.google.co.uk/group/comp.lang.python/tree/browse_frm/thread
> /bd04db20cc1f23bb/36f1f48bb7be1e4b?hl=en&rnum=1&q=set+isSequenceType&_do
> ne=%2Fgroup%2Fcomp.lang.python%2Fbrowse_frm%2Fthread%2Fbd04db20cc1f23bb%
> 2F0454f5debc01c20d%3Fhl%3Den%26lnk%3Dgst%26q%3Dset%2BisSequenceType%26#d
> oc_0454f5debc01c20d
>
> Although there are suggestions that it means simply that you're headed
> in the wrong direction design wise:
> http://www.mail-archive.com/pytho...@python.org/msg11576.html
>
> but then why have isSequenceType at all ?

There are *true* sequences that it can detect, like lists, strings and all
their subclases. For classic classes (that couldn't inherit from builtin
types) all it can do is to guess based on __getitem__. For new style
classes, it checks whether the slot used for __getitem__ is filled.

> Not particularly vital. Just implementing __str__ on some class and if
> one of the members was a sequence
> I was going to format that bit of data in brackets.

As R. Hettinger said, you may add your own knowledge to what
isSequenceType says, to determine whay *you* consider a sequence in this
context.

--
Gabriel Genellina

MarkE

unread,
Dec 19, 2007, 4:03:29 AM12/19/07
to
On 19 Dec, 05:24, "Gabriel Genellina" <gagsl-...@yahoo.com.ar> wrote:
> En Tue, 18 Dec 2007 09:15:12 -0300, English, Mark <Mark.Engl...@rbccm.com>

> escribió:
>
>
>
> >>>> try: set
> >>>> except NameError: from sets import Set as set
> >>>> class myset_fails(set): pass
> >>>> class myset_works(set):
> >>>> def __getitem__(self): pass
> >>>> s = set()
> >>>> fails = myset_fails()
> >>>> works = myset_works()
> >>>> import operator
> >>>> operator.isSequenceType(s) #Not what I expected
> > False
> >>>> operator.isSequenceType(fails) #Not what I expected either
> > False
> >>>> operator.isSequenceType(works) #A hint at what isSequenceType does ?
> > True
>
> > Are sets not sequences ? I didn't think the isSequenceDisclaimer gave
> > false negatives.
>
> No, sets aren't sequences, as they have no order. Same as dicts, which
> aren't sequences either.


Oops. I was under the misapprehension that they were sequences in that
they were sequential but of unknown ordering
e.g. for x in set([someobject, someotherobject, ...]) always iterates
in the same order

Anywho, now I know. Thanks.

Is there a short Pythonic way to determine whether an object is
iterable (iteratable ??) that I haven't thought of (getattr(obj,
'__iter__') ?). Would operator.isIterable() be at all a useful
addition ?

(And what did I do wrong when I posted my original post that I can't
see it in groups.google)

MarkE

unread,
Dec 19, 2007, 4:28:03 AM12/19/07
to
On 19 Dec, 10:03, MarkE <mark.engl...@rbccm.com> wrote:
> > No, sets aren't sequences, as they have no order. Same as dicts, which
> > aren't sequences either.
>
> Oops. I was under the misapprehension that they were sequences
I realise now that this is even explicitly documented:
http://docs.python.org/lib/typesseq.html
"There are six sequence types: strings, Unicode strings, lists,
tuples, buffers, and xrange objects."

> Is there a short Pythonic way to determine whether an object is
> iterable (iteratable ??) that I haven't thought of (getattr(obj,
> '__iter__') ?). Would operator.isIterable() be at all a useful
> addition ?

And here I probably meant container (although the url says sequence
when the article meant container, bit like me):
http://docs.python.org/ref/sequence-types.html
"Containers usually are sequences (such as lists or tuples) or
mappings (like dictionaries), but can represent other containers as
well"

So same question, but perhaps "isContainer()" rather than
"isIterable()"

Gabriel Genellina

unread,
Dec 19, 2007, 12:13:41 PM12/19/07
to pytho...@python.org
En Wed, 19 Dec 2007 06:28:03 -0300, MarkE <mark.e...@rbccm.com>
escribi�:

>> Is there a short Pythonic way to determine whether an object is
>> iterable (iteratable ??) that I haven't thought of (getattr(obj,
>> '__iter__') ?). Would operator.isIterable() be at all a useful
>> addition ?

Yes, I think the only way is to try iter(obj) and see if it succeeds
(that's basically the same as what you do with getattr, but actually
creates the iterator and checks that it's of the right type).

> And here I probably meant container (although the url says sequence
> when the article meant container, bit like me):
> http://docs.python.org/ref/sequence-types.html
> "Containers usually are sequences (such as lists or tuples) or
> mappings (like dictionaries), but can represent other containers as
> well"
>
> So same question, but perhaps "isContainer()" rather than
> "isIterable()"

"container" is too generic. Perhaps you can look if it has a __len__
attribute. But anyone could implement a linked list (the common interfase
don't fit well with those sequence/mapping methods) and would be hard to
deduce whether it is a container or not without further knowledge about it.

--
Gabriel Genellina

Terry Reedy

unread,
Dec 19, 2007, 3:46:31 PM12/19/07
to pytho...@python.org

"MarkE" <mark.e...@rbccm.com> wrote in message
news:ad415199-ba3e-438d...@y5g2000hsf.googlegroups.com...

|| > Is there a short Pythonic way to determine whether an object is
| > iterable (iteratable ??)

Welcome to Python and its neat concept of iterables and iterators.
An iterable is an object that has an __iter__ method that returns an
iterator.
An iterator is an object that has an __iter__ method that returns itself
and a next method that either returns another item or raises StopIteration.
(I omit an older alternative that will disappear in 3.0. Ignore it.)
(Also, in 3.0, next methods will become __next__ methods.)
So iterators are also, intentionally, iterables.
So functions can take arguments that are either by beginning with
it = iter(iterable)
without worrying about whether the iterable already is an iterator.
As Gabriel said, assume that an object returned by iter is an iterable.
Writing an __iter__ method that does not return such would be either a bug
or a nasty trick.

I usually would not bother wrapping iter in a try: block.
Just iterate with 'it' and if it is not an iterator, you will find out.

| And here I probably meant container (although the url says sequence
| when the article meant container, bit like me):
| http://docs.python.org/ref/sequence-types.html
| "Containers usually are sequences (such as lists or tuples) or
| mappings (like dictionaries), but can represent other containers as
| well"

I think 'collection' is a better word that 'container' since 'container'
implies an exclusivity (which is false) that 'collection' does not, at
least not necessarily.

| So same question, but perhaps "isContainer()" rather than
| "isIterable()"

Python 3 will have Abstract Base Classes that will better defined some of
these concepts. So if class authors bother to inherit from them when
appropriate, isinstance(obj, Sequence) or isinstance(obj, Number), for
instance, will tell you.

Terry Jan Reedy

Reply all
Reply to author
Forward
0 new messages