On 28.08.2020 10:30, Stephen J. Turnbull wrote:
M.-A. Lemburg writes:
On 27.08.2020 17:53, David Mertz wrote:
Suppose we didn't have dict.get(). I would then probably write:
val = mydict[key] if key in mydict else None
Likewise, since we don't have list.get(), I would write:
val = mylist[N] if len(mylist) >- N-1 else None
Neither of those is impractical, but in both cases .get(key) seems to express the intent in a more obvious way.
Really ?
I think David is comparing the .get syntax to the if-else syntax.
First of all, he got the if-else wrong, which is a sign that .get is easier to use, at least for writers and quite likely for readers.
Second I agree that ".get" is easier to read and understand (especially with explicit default, as you advocate). It's even more stark if you're after a component of the list element:
val = mylist[N if len(mylist) > N else default].content
vs.
val = mylist.get(N, default).content
Let me try again :-)
Getting an item from a bag of unknown items can easily fail, because you don't what's in the bag until you try to find the item.
Trying to access an item from a non-existing bucket in an array will always fail. You know that in advance, since the bucket doesn't exist as per the array properties. You don't have to try finding it first.
But this isn't a C array. You don't know the length from the syntax. So you have to "do work" to discover the bucket isn't there before you access -- or you can delegate to the interpreter and catch IndexError. Given how precise IndexError is (it only catches integer arguments that fall outside the range of the array), I don't really see the argument for refusing to encapsulate the try in a .get method, or that its semantics differ from explicit bounds-checking.
It seems to me that you're expressing a preference for "look before you leap" over "easier to ask forgiveness than permission" in the case of array indicies, which is a stylistic thing. It's a style I prefer in this case, but I can also see how other people would prefer a different style, one that makes sense to encapsulate in .get. Is there something more than stylistic preference that I'm missing?
I was trying to explain why dict.get() is different than the suggested list.get(). dict.get() was added since the lookup is expensive and you want to avoid having to do this twice in the common case where the element does exist. It was not added as a way to hide away an exception, but instead to bypass having to generate this exception in the first place. dict.setdefault() has a similar motivation. list.get() merely safes you a line of code (or perhaps a few more depending on how you format things), hiding away an exception in case the requested index does not exist. If that's all you want, you're better off writing a helper which hides the exception for you. I argue that making it explicit that you're expecting two (or more) different list lengths in your code results in more intuitive and maintainable code, rather than catching IndexErrors (regardless of whether you hide them in a method, a helper, or handle them directly). So this is more than just style, it's about clarity of intent. -- Marc-Andre Lemburg eGenix.com Professional Python Services directly from the Experts (#1, Aug 28 2020)
Python Projects, Coaching and Support ... https://www.egenix.com/ Python Product Development ... https://consulting.egenix.com/
::: We implement business ideas - efficiently in both time and costs ::: eGenix.com Software, Skills and Services GmbH Pastor-Loeh-Str.48 D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg Registered at Amtsgericht Duesseldorf: HRB 46611 https://www.egenix.com/company/contact/ https://www.malemburg.com/