11 ms·
And as that comment correctly reminds us, .get()/getattr/etc exists for that very reason and I will almost always reject a code review that trys such an operati
by jsmthrowaway 10y ago
And as that comment correctly reminds us, .get()/getattr/etc exists for that very reason and I will almost always reject a code review that trys such an operation instead of using .get(). Don't do this:
try:
bar = dictionary['foo']
except KeyError as ex:
# handling
Do this:
bar = dictionary.get('foo')
if bar is None:
# optional handling, None might be OK
Or this:
bar = dictionary.get('foointeger', 0)
# now you don't even need handling
You avoid scope issues with the try block, stack unwinding, all sorts of issues. This works for attributes too with getattr(). It is quite easy to work in Python without try/except, for the most part, especially if your types are well-built.
That addresses the specific case mentioned, of course, but not others. Occasionally you do have to handle exceptions but this almost always revolves around I/O, and you can isolate those portions in well-defined types that expose functionality to the rest of your program instead of trying every few lines.
- mangeletti 10y agoYou're confusing improper lack of abstraction with error handling methodology. The place to use EAFP in this example is in dict.get itself: def get(self, key, default=SENTINAL): try: return self[key] except KeyError: if default is not SENTINAL: return SENTINAL raise (made-up implementation ^ I'm not sure if Python's stdlib actually does exactly that) I absolutely love Python's exception handling, and I strongly subscribe to EAFP (not just in coding, even), but I rarely use try/except, because most of the time your business logic (where I spend most of my time) should be delegating to something (external/internal library, etc.) that handles exceptions, rather than littering your business logic with low level logic.
- jsmthrowaway 10y agoI'm not confused about anything aside from your claiming I'm confused and then agreeing with me in your conclusion. I'm reacting to the explanation of EAFP using that example. And no, Python's implementation does not do that, since (a) I'm almost positive dict.get is not Python and (b) your code is quite obviously incorrect.
- deleted 10y ago[deleted]
- mangeletti 10y ago> Your code is quite obviously incorrect. You sho-bout that? https://repl.it/Cbu8/4 https://repl.it/Cbu8/4 If you're new to programming, you can learn a lot more by listening than by arguing.
- jsmthrowaway 10y agoYes, I'm quite sure, since your code above contains "return SENTINAL" and you fixed the bug in your link. (It's also sentinel.) It's doubly incorrect even in a specification sense, since dict.get defaults to None by returning NULL (it is implemented in C in CPython[0][1], and I'm assuming you can read those references based on your assertion of skill) and no sentinel is used or needed. In your Python translation, that'd be defaulting to None instead of a sentinel. It's triply incorrect because dict.get also does not re-raise a KeyError; it always returns something barring a runtime error of some kind or asking for a key that cannot be hashed: >>> {}.get({}) is None TypeError: unhashable type: 'dict' >>> {}.get("key") is None True >>> {}.__hash__ is None True >>> "key".__hash__ is None False Let me fix your example for you: def get(self, key, default=None): try: return self[key] except KeyError: return default Although really, the C implementation does this, indirectly: def get(self, key, default=None): return self[key] if key in self else default The reason I say indirectly is because (a) there's no exception handling in use in the C case and (b) there's no equivalent to the hash table lookup failing when written in Python, so it's an inexpressible concept. That Python will search twice, while the C does not. The KeyError except is a nice analog, but CPython does not futz with stack frames at all if the key lookup fails, so it's not directly comparable to your version. My final version is the closest you'll get to translating what Python does to Python. If you're speaking with someone new, you can learn a lot more by not condescendingly assuming competence of the other party, particularly when they correctly spotted those three problems and you didn't. I trust this reply will alleviate the misconception. [0]: https://github.com/python/cpython/blob/master/Objects/dictobject.c#L2632 https://github.com/python/cpython/blob/master/Objects/dictob... [1]: https://github.com/python/cpython/blob/master/Objects/dictobject.c#L2347-L2374 https://github.com/python/cpython/blob/master/Objects/dictob...
- throwaway274739 10y agoI don't mind the "try ... except" version for the cases where most of the time the key will be present. Two reasons for this: 1) the "except" semantics help hit home the point you expect the key to be there most of the time 2) in cases where the exception will rarely be raised, the "try ... except" route runs faster than the ".get() ... if" route.