I didn’t say there is a grammatical error. I meant we shouldn’t read it objects <...> that implements
but method that implements
.
Well, it doesn’t matter if you disagree. The sentence can also be parsed the other way around. There are no parentheses or arrows to clearly indicate how to associate the subordinate clause and the conjunction. You might have a favorite interpretation, but both are there.
Not in a grammatically correct way, it cannot.
You are simply wrong. An again, there is no grammatical error. Grammatically the sentence is well-formed.
“Objects of any classes that implements sequence semantics” is a grammatically correct sentence?
Yes. It is a grammatically correct sentence. But like most sentences, only if it is not misquoted. E.g. by only providing half of it, and omitting the other half (especially when that contains the verb).
The full original is:
Examples of iterables include all sequence types (such as list, str, and tuple) and some non-sequence types like dict, file objects, and objects of any classes you define with an __iter__() method or with a __getitem__() method that implements sequence semantics.
UPD: Yes, it’s grammatically correct.
And we think this sentence says “the class’ object from the topic start is an iterable (any classes you define with an __iter__() method
)”.
If so, list(X)
is correct (Using the type constructor: list() or list(iterable)
).
On the other hand, @abessman , we had
Lists may be constructed in several ways:
- Using the type constructor:
list()
orlist(iterable)
iterable may be either a sequence, a container that supports iteration, or an iterator object.
So, maybe iterable
here doesn’t refer to https://docs.python.org/3/glossary.html#term-iterable?
The subject of “implements” in the complete sentence is still unambiguously “method”.
Is it?
>>> class Iterable:
... def __getitem__(self, item):
... if type(item) is int and 0 <= item < 4:
... return item **2
... raise IndexError
...
>>> list(Iterable())
[0, 1, 4, 9]
As long as __getitem__
implements sequence semantics, the object IS iterable. I’m not sure why this doesn’t make sense to you, but regardless, it is a fact.
My confusion stemmed from the definition of “sequence semantics”, as the definition of sequence specifically mentions both __getitem__
and __len__
.
But I guess an iterator can be an iterable that is not a sequence, but is “sequence-like” in that it lacks __len__
but has a suitable __getitem__
.
By the way this statement itself doesn’t conform with https://docs.python.org/3/glossary.html#term-sequence:
sequence:
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.
To be a sequence, an object needs getitem and len, both of which must fulfil sequence semantics.
To be iterable, an object needs getitem, which must fulfil sequence semantics. (Or have iter, of course.)
UPD: @Rosuav , do you mean sequence
is not equal to sequence semantic
?
One more time. The whole picture.
https://docs.python.org/3/library/stdtypes.html#list:
Lists may be constructed in several ways:
- Using the type constructor:
list()
orlist(**iterable**)
iterable may be either a sequence, a container that supports iteration, or an iterator object.
https://docs.python.org/3/glossary.html:
iterable:
An object capable of returning its members one at a time. Examples of iterables include all sequence types (such aslist
,str
, andtuple
) and some non-sequence types likedict
,file
objects, and objects of any classes you define with an__iter__()
method or with a__getitem__()
method that implements sequence semantics.
sequence:
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.
As I said above, we could change:
Lists may be constructed in several ways:
- Using the type constructor:
list()
orlist(not_an_iterable_but_another_term)
not_an_iterable_but_another_term may be either a sequence, a container that supports iteration, or an iterator object.
to make the logic correct.
Then:
list
may receive not_an_iterable_but_another_term.
not_an_iterable_but_another_term: if any of statements are true:
- is a sequence, or
- is a container that supports iteration, or
- is an iterator object.
iterable: if any of statements are true:
list
,str
,tuple
, etc. (sequence type), ordict
,file
, or- with
__iter__
, - with
__getitem__
(sequence semantic), or - (??? more?).
sequence: if every statement is true:
- is an iterable,
- with
__getitem__
, - with
__len__
.
(??? is this reducible?)
sequence type: < list of types here >
sequence semantic: a class with __getitem__
method. (???)
container that supports iteration: (??? what’s is it? do we really need it?)
iterator: <…>
Why do you want to add so much stuff:
-
the list constructor is fully correctly specified by
list(iterable)
. -
iterable is anything that can be iterated: Either it has a defined
__iter__
, or it has a__getitem__
with sequence semantics -
sequence has
__getiem__
and__len__
The only problem is that currently sequence semantics isn’t defined, and linking to sequence is confusing.
What is meant is that if an object does not have __iter__
, but it does have __getitem__
, python will automatically do stuff equivalent to the following code:
def iter_getitem(obj):
for i in count(0):
try:
yield obj[i]
except IndexError:
return
not_an_iterable_but_another_term is completely pointless. iterable is the correct term. Misbehaving __len__
methods are not to be taken into consideration.
No, it isn’t Compare above, please.
Ok, a simpler solution:
Lists may be constructed in several ways:
- Using the type constructor:
list()
orlist(sequence)
orlist(container)
orlist(iterator)
.See sequence, iterator in the Glossary.
container
is a container that supports iteration (??? needs a definition).
Yes, it is. Everything you listed under not_an_iterable_but_another_term
is an iterable, and I can’t think of anything that is an iterable that doesn’t fall into that category. Please give me an object that is in one set but not in the other.
I started the topic with it:
class A:
def __iter__(self):
for i in range(8):
yield i
def __len__(self):
raise NotImplementedError
iterable:
An object capable of returning its members one at a time. Examples of iterables include all sequence types (such as list, str, and tuple) and some non-sequence types like dict, file objects, and objects of any classes you define with an__iter__()
method or with a__getitem__()
method that implements sequence semantics.
It is an iterable but list()
can’t handle it.
… And? That is in both categories. It can be passed to list
and it falls into the category of iterable. What breaks in OP is a misbehaving __len__
. __len__
should return a number between 0 and sys.maxsize
or raise a TypeError
(in which case list
behaves as if it isn’t defined). You doing something wrong (i.e. raising NotImplementedError
) just means that a different contract isn’t specified enough, not that the documentation is wrong.
It can’t be passed.