108 lines
2.7 KiB
Plaintext
108 lines
2.7 KiB
Plaintext
== Why is this an issue?
|
|
|
|
The https://www.python.org/dev/peps/pep-0234/#python-api-specification[iterator protocol] specifies that an iterator object should have
|
|
|
|
* a ``++__next__++`` method retrieving the next value or raising ``++StopIteration++`` when there are no more values left.
|
|
* an ``++__iter__++`` method which should always return ``++self++``. This enables iterators to be used as sequences in for-loops and other places.
|
|
|
|
This rule raises an issue when a class has a ``++__next__++`` method and either:
|
|
|
|
* it doesn't have an ``++__iter__++`` method.
|
|
* or its ``++__iter__++`` method does not return "self".
|
|
|
|
|
|
=== Noncompliant code example
|
|
|
|
[source,python]
|
|
----
|
|
class MyIterator: # Noncompliant. Class has a __next__ method but no __iter__ method
|
|
|
|
def __init__(self, values):
|
|
self._values = values
|
|
self._index = 0
|
|
|
|
def __next__(self):
|
|
if self._index >= len(self._values):
|
|
raise StopIteration()
|
|
value = self._values[self._index]
|
|
self._index += 1
|
|
return value
|
|
|
|
|
|
class MyIterator:
|
|
def __init__(self, values):
|
|
self._values = values
|
|
self._index = 0
|
|
|
|
def __next__(self):
|
|
if self._index >= len(self._values):
|
|
raise StopIteration()
|
|
value = self._values[self._index]
|
|
self._index += 1
|
|
return value
|
|
|
|
def __iter__(self):
|
|
return 42 # Noncompliant. This __iter__ method does not return self
|
|
|
|
|
|
class MyIterable: # Ok. This is an iterable, not an iterator, i.e. it has an __iter__ method but no __next__ method. Thus __iter__ doesn't have to return "self"
|
|
|
|
def __init__(self, values):
|
|
self._values = values
|
|
|
|
def __iter__(self):
|
|
return MyIterator(self._values)
|
|
----
|
|
|
|
|
|
=== Compliant solution
|
|
|
|
[source,python]
|
|
----
|
|
class MyIterator:
|
|
def __init__(self, values):
|
|
self._values = values
|
|
self._index = 0
|
|
|
|
def __next__(self):
|
|
if self._index >= len(self._values):
|
|
raise StopIteration()
|
|
value = self._values[self._index]
|
|
self._index += 1
|
|
return value
|
|
|
|
def __iter__(self):
|
|
return self
|
|
|
|
class MyIterable:
|
|
def __init__(self, values):
|
|
self._values = values
|
|
|
|
def __iter__(self):
|
|
return MyIterator(self._values)
|
|
----
|
|
|
|
|
|
== Resources
|
|
|
|
* https://www.python.org/dev/peps/pep-0234/#python-api-specification[PEP 234 - Iterators]
|
|
* https://docs.python.org/3/library/stdtypes.html#iterator-types[Python documentation - Iterator Types]
|
|
|
|
|
|
ifdef::env-github,rspecator-view[]
|
|
|
|
'''
|
|
== Implementation Specification
|
|
(visible only on this page)
|
|
|
|
include::message.adoc[]
|
|
|
|
include::highlighting.adoc[]
|
|
|
|
'''
|
|
== Comments And Links
|
|
(visible only on this page)
|
|
|
|
include::comments-and-links.adoc[]
|
|
endif::env-github,rspecator-view[]
|