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)
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.
On Wed, 3 May 2023 at 18:52, Thomas Passin <list1@tompassin.net> wrote:
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 fromDepending on what you want to give and receive, enumerate(reversed(a))
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. >>
will do the job here. Otherwise list() or tuple() can achieve some of
the same things.
I don't think that is equivalent to the intended behaviour:
reversed(enumerate(a)) # zip(reversed(range(len(a))), reversed(a)) enumerate(reversed(a)) # zip(range(len(a)), reversed(a))
In principle for a sequence input enumerate(a) could be something that behaves like a sequence and therefore could be reiterated or reversed
etc. The enumerate(a).__reversed__ method could then delegate to a.__reversed__ and a.__len__ if they exist. This could be confusing
though because the possible behaviour of enumerate(a) would be
different depending on the type of a.
--
Oscar
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.
On 5/3/2023 3:46 PM, Oscar Benjamin wrote:
On Wed, 3 May 2023 at 18:52, Thomas Passin <list1@tompassin.net> wrote:
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.
I don't think that is equivalent to the intended behaviour:
reversed(enumerate(a)) # zip(reversed(range(len(a))), reversed(a)) enumerate(reversed(a)) # zip(range(len(a)), reversed(a))
I don't think we know the intended behavior here. The OP did not say
what type of object should be returned. He only wanted an expression
that would run. Apparently the result should be an enumeration of
variable "a" but with "a" reversed. Is "a" supposed to be a sequence?
An iterator? Presumably the result was expected to be an enumeration,
which is to say an iterator, and enumerate(reversed(a)) would return an iterator.
... print("E-R", i, n)a = [10, 20, 30, 40, 50]
for i, n in enumerate(reversed(a)):
... print("R-E", i, n)for i, n in reversed(list(enumerate(a))):
... print("Zip", i, n)for i, n in zip(reversed(range(len(a))), reversed(a)):
So
you're asking for map to be able to return an iterator if given an
iterator, or an adapter if given an adapter. That makes it quite
complicated to use and reason about.
On 5/3/2023 5:45 AM, fedor tryfanau wrote:problems
I've been using python as a tool to solve competitive programming
type.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
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.
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 300 |
Nodes: | 16 (2 / 14) |
Uptime: | 64:06:33 |
Calls: | 6,712 |
Files: | 12,244 |
Messages: | 5,356,076 |