[Python-ideas] __call__ on lists, dicts etc.
Hi all,
I've been working in q and k, which is where this idea comes from.
My idea is to make lists and dicts callable, with __call__ =
__getitem__.
So that:
[3,4,5](1) gives 4
{'a':1, 'b': 2}('b') gives 2
Arguably a list is a function which maps from range(len(list)) to the
list entries, and a dictionary is a function that maps from keys to
values.
This would mean that functions designed to take functions, can be
repurposed to take data, for example:
map(lst, idxs) instead of (lst[i] for i in idxs) or map(lambda x:
lst[x], idxs)
map(dct, lst) instead of (dct[l] for l in lst)
sorted(range(len(lst)), key=lst) to calculate the equivalent of
np.argsort
max(range(len(lst)), key=lst) to calculate the equivalent of np.argmax
I couldn't find this being discussed before. Does anyone like it? There
is room for confusion as it would mean that e.g. filter([1,2], [0,1])
would give [0,1] whilst [1] might be expected.
Best,
George Harding
p.s. Thank you to everyone for their work on such a wonderful language.
___
Python-ideas mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at
https://mail.python.org/archives/list/[email protected]/message/MZCYYFDDNJ4ETXLKAYFRU76LB3JWLZOJ/
Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: __call__ on lists, dicts etc.
Well there is already a function you can call for these, __getitem__:
lst_getter = lst.__getitem__
map( lst_getter, idxs)
sorted(range(len(lst)), key=lst_getter)
max(range(len(lst)), key=lst_getter)
dct_getter = dct.__getitem__
map(dct, lst) instead of (dct[l] for l in lst)
If you find yourself preferring this map() style of code a lot (rather than
using generator expressions), you can make a utility function:
def getter(obj):
return obj.__getitem__
If anything is going to be proposed, I'd suggest rather than making these
callable directly, add a utility function that calls the dunder method.
So:
len() is to __len__
as:
getter() is to __getitem__
But I'm not proposing this, I'm just suggesting it as a bit better
alternative to the initial idea.
---
Ricky.
"I've never met a Kentucky man who wasn't either thinking about going home
or actually going home." - Happy Chandler
On Mon, Oct 5, 2020 at 8:42 AM wrote:
> Hi all,
>
> I've been working in q and k, which is where this idea comes from.
>
> My idea is to make lists and dicts callable, with __call__ =
> __getitem__.
>
> So that:
>
> [3,4,5](1) gives 4
> {'a':1, 'b': 2}('b') gives 2
>
> Arguably a list is a function which maps from range(len(list)) to the
> list entries, and a dictionary is a function that maps from keys to
> values.
>
> This would mean that functions designed to take functions, can be
> repurposed to take data, for example:
>
> map(lst, idxs) instead of (lst[i] for i in idxs) or map(lambda x:
> lst[x], idxs)
> map(dct, lst) instead of (dct[l] for l in lst)
>
> sorted(range(len(lst)), key=lst) to calculate the equivalent of
> np.argsort
> max(range(len(lst)), key=lst) to calculate the equivalent of np.argmax
>
> I couldn't find this being discussed before. Does anyone like it? There
> is room for confusion as it would mean that e.g. filter([1,2], [0,1])
> would give [0,1] whilst [1] might be expected.
>
> Best,
>
> George Harding
>
> p.s. Thank you to everyone for their work on such a wonderful language.
> ___
> Python-ideas mailing list -- [email protected]
> To unsubscribe send an email to [email protected]
> https://mail.python.org/mailman3/lists/python-ideas.python.org/
> Message archived at
> https://mail.python.org/archives/list/[email protected]/message/MZCYYFDDNJ4ETXLKAYFRU76LB3JWLZOJ/
> Code of Conduct: http://python.org/psf/codeofconduct/
>
___
Python-ideas mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at
https://mail.python.org/archives/list/[email protected]/message/OPXPI5KI3YZ2MCNSVHU3E2S7KTYNFXHU/
Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: __call__ on lists, dicts etc.
Please no. If you want lisp, use lisp (or something in the lisp family)
On Mon, Oct 5, 2020 at 5:53 AM Ricky Teachey wrote:
> If you find yourself preferring this map() style of code a lot (rather
than using generator expressions), you can make a utility function:
def getter(obj):
return obj.__getitem__
or use the ones that are already in the stdlib:
In [3]: operator.attrgetter?
Init signature: operator.attrgetter(self, /, *args, **kwargs)
Docstring:
attrgetter(attr, ...) --> attrgetter object
Return a callable object that fetches the given attribute(s) from its
operand.
After f = attrgetter('name'), the call f(r) returns r.name.
After g = attrgetter('name', 'date'), the call g(r) returns (r.name,
r.date).
After h = attrgetter('name.first', 'name.last'), the call h(r) returns
(r.name.first, r.name.last).
-CHB
---
Ricky.
"I've never met a Kentucky man who wasn't either thinking about going home
or actually going home." - Happy Chandler
> On Mon, Oct 5, 2020 at 8:42 AM wrote:
>
>> Hi all,
>>
>> I've been working in q and k, which is where this idea comes from.
>>
>> My idea is to make lists and dicts callable, with __call__ =
>> __getitem__.
>>
>> So that:
>>
>> [3,4,5](1) gives 4
>> {'a':1, 'b': 2}('b') gives 2
>>
>> Arguably a list is a function which maps from range(len(list)) to the
>> list entries, and a dictionary is a function that maps from keys to
>> values.
>>
>> This would mean that functions designed to take functions, can be
>> repurposed to take data, for example:
>>
>> map(lst, idxs) instead of (lst[i] for i in idxs) or map(lambda x:
>> lst[x], idxs)
>> map(dct, lst) instead of (dct[l] for l in lst)
>>
>> sorted(range(len(lst)), key=lst) to calculate the equivalent of
>> np.argsort
>> max(range(len(lst)), key=lst) to calculate the equivalent of np.argmax
>>
>> I couldn't find this being discussed before. Does anyone like it? There
>> is room for confusion as it would mean that e.g. filter([1,2], [0,1])
>> would give [0,1] whilst [1] might be expected.
>>
>> Best,
>>
>> George Harding
>>
>> p.s. Thank you to everyone for their work on such a wonderful language.
>> ___
>> Python-ideas mailing list -- [email protected]
>> To unsubscribe send an email to [email protected]
>> https://mail.python.org/mailman3/lists/python-ideas.python.org/
>> Message archived at
>> https://mail.python.org/archives/list/[email protected]/message/MZCYYFDDNJ4ETXLKAYFRU76LB3JWLZOJ/
>> Code of Conduct: http://python.org/psf/codeofconduct/
>>
> ___
> Python-ideas mailing list -- [email protected]
> To unsubscribe send an email to [email protected]
> https://mail.python.org/mailman3/lists/python-ideas.python.org/
> Message archived at
> https://mail.python.org/archives/list/[email protected]/message/OPXPI5KI3YZ2MCNSVHU3E2S7KTYNFXHU/
> Code of Conduct: http://python.org/psf/codeofconduct/
>
--
Christopher Barker, PhD
Python Language Consulting
- Teaching
- Scientific Software Development
- Desktop GUI and Web Development
- wxPython, numpy, scipy, Cython
___
Python-ideas mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at
https://mail.python.org/archives/list/[email protected]/message/XVUOASRZOZHXI2L7UXU4YNWIAB5P5BQC/
Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Method to efficiently advance iterators for sequences that support random access
str_iterator, bytes_iterator, range_iterator, list_iterator, and tuple_iterator (and probably others) should have a method that is capable of efficiently advancing the iterator, instead of having to call next repeatedly. I suggest adding an itertools.advance function which dispatches to a dunder __advance__ method (if one exists) or, as a fallback, calls next repeatedly. Then, the iterators mentioned above (and any others capable of efficiently doing so) would implement __advance__, which would directly manipulate their index to efficiently "jump" the desired number of elements in constant-time rather than linear-time. For example, if you have a large list and want to iterate over it, but skip the first 5 elements, you should be able to do something like: it = iter(mylist) itertools.advance(it, 5) Note that you technically can do this with itertools.islice by supplying a start value, but itertools.islice effectively just repeatedly calls next on your behalf, so if you're skipping a lot of elements, it's unnecessarily slow. As a side note, I noticed that list_iterator has __setstate__ which can be used to (more or less) accomplish this, but that seems very hack-y. Although it is setting the index directly (rather than adding to it), so it'd be more awkward to use if the iterator is already partially exhausted. it = iter(mylist) it.__setstate__(5) ___ Python-ideas mailing list -- [email protected] To unsubscribe send an email to [email protected] https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/[email protected]/message/3FYI47IU2PKE42WWXL4AG7UNT4GBOWMD/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Method to efficiently advance iterators for sequences that support random access
You can use slice: new_iterator = iterator[50001:] it2 = iter(new_iterator) or range: for i in range(50001, len(iterator)): x = iterator[i] ___ Python-ideas mailing list -- [email protected] To unsubscribe send an email to [email protected] https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/[email protected]/message/KP6DAY4YQVA6LOX2XCRMIAEK5W3JZVG5/ Code of Conduct: http://python.org/psf/codeofconduct/
