An "adapter", superset of an iterator

fedor tryfanau fedor.tryfanau at gmail.com
Wed May 3 05:45:36 EDT 2023


I've been using python as a tool to solve competitive programming problems
for a while now and I've noticed a feature, python would benefit from
having.
Consider "reversed(enumerate(a))". This is a perfectly readable code,
except it's wrong in the current version of python. That's because
enumerate returns an iterator, but reversed can take only a sequence type.

The feature I am describing (and proposing) solves this.
Introducing an adapter type: this is an iterator, but it's items can be
accessed out of order.
More formally it has to:
1. Have __getitem__ to allow access by index
2. Have __len__
3. Be immutable
(It is a lot like the sequence protocol)

An adapter can be converted to an iterator by accessing it from 0 to
len(adapter). Which is done by iter(). (or by __iter__, I don't know which
implementation would be "right")
```
iter(a)
#is equivalent to
(a[i] for i in range(len(a)))
```
For example any tuple is a valid adapter and any list can be easily
converted to one.

Built-in adapter-generators:
"map" function should really return an adapter.
```
#possible implementation
m=map(lambda x:x+1,[1,2,3,4,5])
#lambda is not called
print(m[3])# gives 5 by calling the lambda on list's 3rd element, which is 4
#simplified implementation
class map:
    def __init__(self,f,a):
        self.f=f
        self.a=a
    def __getitem__(self,idx):
        return self.f(self.a[idx])
    def __len__(self):
        return len(self.a)
```
enumerate should really return an adapter
```
#simplified implementation
class enumerate:
    def __init__(self,a):
        self.a = a
    def __getitem__(self,idx):
        return idx,self.a[idx]
    def __len__(self):
        return len(self.a)
```
reversed should really return an adapter
```
#simplified implementation
class reversed:
    def __init__(self,a):
        self.a = a
        self.length=len(a)
    def __getitem__(self,idx):
        return self.a[self.length-idx-1]
    def __len__(self):
        return self.length
```
zip should really return an adapter
range should really return an adapter
filter should *not* return an adapter

All of those functions return an adapter and take in an adapter. But some
(excluding "reversed") should be able take an iterator and return an
iterator.
So the way I imagine a possible release version to work is that
"reversed(enumerate(a))" works if a is an adapter and throws an exception
if not

Perhaps there should be even an adapter comprehension:
```
Add1 = (a+1 for a)
#is equivalent to
Add1 = lambda s: map((lambda a: a+1),s)
transformed = Add1([1,2,3])
print(transformed[1])# should be 3
```

This adapter feature also allows you to not use a key argument "key=" for
certain functions (which could be non-existing). For example bisect.bisect
functions before 3.10 didn't have a key= argument. Some third-party
libraries could do this with it's functions too.

(Subject to change)


More information about the Python-list mailing list