4 ms·
> In that way `sorted` _is_ totally consistent - it always takes an iterable and returns a list of the elements except Iterable is the wrong "interface" in Py
by peoplefromibiza 4y ago
> In that way `sorted` _is_ totally consistent - it always takes an iterable and returns a list of the elements
except Iterable is the wrong "interface"
in Python it is defined as
> An iterable is any Python object capable of returning its members one at a time, permitting it to be iterated over in a for-loop.
which is not always what you want for sorting
quicksort doesn't work one element at a time
so basically you have to extract all the elements before sorting them
what about infinite streams?
At least Ruby Enumerable mixins explicitly states that
> The Enumerable mixin provides collection classes with several traversal and searching methods, and with the ability to __sort__.
Another problem with sorted is that it accepts any iterable, true, returning a list of items, but it is not clear how you can tell if the object is an iterbale or not
>>> sorted(123)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object is not iterable
ok
>>> isinstance(123, iterable)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'iterable' is not defined
mmmm
maybe it's because int is not iterable?
>>> isinstace("abc", iterable)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'iterable' is not defined
so the solutions are
# fails for strings in Python 2
>>> try:
_ = iter(some_object)
except TypeError as te:
print('is not iterable')
or
# if 2.6 >= Python < 3.3
from collections import Iterable
# if Python >= 3.3
from collections.abc import Iterable # <- personal note, abc stands for...? core maybe?
# no idea on how to do it in Python < 2.6
>>> isinstance("abc", Iterable)
True
not only it's very ugly, but it can also fail in mysterious ways. As per documentation
Checking isinstance(obj, Iterable) detects classes that are registered as Iterable or that have an __iter__() method, but it does not detect classes that iterate with the __getitem__() method. The only reliable way to determine whether an object is iterable is to call iter(obj).
while in Ruby it's straightforward
[3] pry(main)> [1, 2].is_a? Enumerable
=> true
[4] pry(main)> "abc".is_a? Enumerable
=> false
[5] pry(main)> "abc".chars.is_a? Enumerable
=> true