An "adapter", superset of an iterator
Thomas Passin
list1 at tompassin.net
Wed May 3 13:30:50 EDT 2023
On 5/3/2023 5:45 AM, fedor tryfanau wrote:
> 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.
Depending on what you want to give and receive, enumerate(reversed(a))
will do the job here. Otherwise list() or tuple() can achieve some of
the same things.
> 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