Mahesha999
Mahesha999

Reputation: 24811

Intuitions behind python API design

Usually while writing code, I tend to make mistakes with some function as those functions signatures dont follow my intuition. Or more appropriately my intuition do not follow the design thinking behind these functions. I always wondered if python APIs have some inconsistencies.

For example, in python, we have:

>>> ','.join(['1','2','3'])
'1,2,3'

>>> '1,2,3'.split(',')
['1', '2', '3']

Many times I find myself doing:

['1','2','3'].join(',')

and some times (/ very rarely):

','.split('1,2,3')

Similarly I find this somewhat frustrating:

>>> sorted([1,2,3])
[1, 2, 3]

>>> reversed([1,2,3])
<list_reverseiterator object at 0x000002008932A95

That is, one list function returns list, while other returns an iterator. To save me some time (usually in timed coding competition), I usually end up doing extra list():

>>> list(reversed([1,2,3]))
[3, 2, 1]

>>> list(sorted([1,2,3]))
[1, 2, 3]

I believe there must be some API design standards or technical considerations behind these and am unaware of them. Can someone please share their understanding regarding these, so that it will become part of my intuition and I will do less mistakes. Or is it just the coding practice that will help me make less mistakes? Also, these are just couple of the things that I can recall now, which I usually make mistakes at. Can you share similar API confusions and intuitions behind them that you face (if you face them at all)?

Upvotes: 2

Views: 58

Answers (1)

deceze
deceze

Reputation: 522519

You need to understand the reasoning behind each one.

','.join(['1','2','3'])

Any iterable can be joined by a string. Not just lists. If you'd design it like [...].join(','), each possible iterable would need to implement its own join method. You'd need list.join, tuple.join, dict.join etc. Your own classes would all need to implement their own join method.

Thus is makes more sense for join to be a method of str which accepts any arbitrary iterable.

'1,2,3'.split(',')

Conversely, it only makes sense to split a string, so split is a method on str. You may be able to split other types as well, but how that works would differ per type, so it makes sense for each type to define its own split method as makes sense.


sorted([1,2,3])

You must treat the entire list as a whole in order to sort it, all the list contents get shuffled around inside it during the sort operation. So you get a list as return value, as the operation intrinsically produces one anyway.

reversed([1,2,3])

Conversely, you do not need to produce a complete reversed copy of the list in memory in order to reverse it; you can just go through it one item at a time. Often you want to iterate over a collection in the reverse order, not store a reversed collection. So to make it efficient and save memory, it returns an efficient iterator which allows you to do this, instead of forcing you to double your memory usage. If you need to store this as a reversed list, you can do it yourself with list(reversed(...)).

Upvotes: 1

Related Questions