[Python-ideas] get() method for list and tuples

Steven D'Aprano steve at pearwood.info
Tue Feb 28 18:56:16 EST 2017


On Tue, Feb 28, 2017 at 04:16:28PM +0100, Michel Desmoulin wrote:
> 
> 
> Le 28/02/2017 à 15:45, Steven D'Aprano a écrit :
> > On Tue, Feb 28, 2017 at 12:54:26PM +0100, Michel Desmoulin wrote:
> >> dict.get() is a very useful method, but for lists and tuples, we need to
> >> rely on try/except instead.
> > 
> > No you don't. You can use slicing.
> > 
> > alist = [1, 2, 3]
> > print(alist[99:100])  # get the item at position 99
> 
> No this gives you a list of one item or an empty list.

I am aware of that. I'm just saying you don't have to use try...except, 
you can use slicing instead. Obviously you have to adapt the code since 
you are getting a list not a single item:

# may fail, if alist is empty
if alist[0] == "spam": ...

# cannot fail
if alist[0:1] == ["spam"]: ...


This is *especially* useful for strings since a slice of a string is a 
string, and an item from a string is still a string.



> dict.get('key', default_value) let you get a SCALAR value, OR a default
> value if it doesn't exist.
> 
> It's a very different use case.

For a default, use "or":

first_item = (alist[0:1] or ["ham"])[0]

But honestly, in my experience the number of times I actually needed 
something like that is tiny.



> > In my experience, dict.get is very useful, but list.get only *seems* 
> > useful. I've written my own version:
> > 
> > def get(alist, pos, default=None):
> >     try:
> >         return alist[pos]
> >     except IndexError:
> >         return default
> > 
> > 
> 
> Based on your rational, we would just reject dict.get as well the first
> time it's implemented.

I just said that dict.get is proven to be useful. There's no doubt that 
it is useful.


> > but then struggled to find a good use for it. It seems like it ought to 
> > be useful, but in practice I found that it was only covering up bugs in 
> > my code. 
> 
> How so ? "get the element x or a default value if it doesn't exist" seem
> at the contrary, a very robust approach.

A very robust approach **for what** ?

What are you trying to do? Why are you indexing into arbitrary positions 
of a list without knowing whether or not there is something there?

List are not dicts and they are used differently. It is very common, and 
useful, to want to look up a key in a dict without knowing if it exists, 
and do something with a default if it doesn't exist. This is so useful 
that Python gives us *at least* four different ways to avoid using a 
try...except:

- dict.get
- dict.setdefault
- dict subclasses with __missing__ defined
- collections.defaultdict


all of which solve slightly different use-cases.

But *in my experience* it is rare to need to look up some arbitrary 
item in a list that may not even exist, and if I find myself doing so, 
it probably means my code is badly designed and I'm going to have 
trouble later on.

For the tiny number of exceptions, I can use the existing solutions: 
either try...except, or slicing as above.

If your experience is different from mine, please explain your use-case.


> Plus it's consistent. It's only fair to expect it to exists after you
> learn about dict.get.

As quoted in PEP 8, "A foolish consistency is the bugbear of little 
minds."

Lists and dicts aren't the same thing and don't offer the same 
interface. There's no dict.sort or list.update, dicts don't support 
slicing, concatenation or repetition, there's no list.popitem. Dicts 
have keys and values, lists have items or elements.

list.get has to prove its usefulness on its own, not just because 
dict.get is useful.


> First places where I missed it at the top of my head was *args, sys.argv
> personnaly.

Missed it for what? What are you trying to do? Don't assume that it is 
so obvious that everyone will instantly guess your use-case.



-- 
Steve


More information about the Python-ideas mailing list