This post summarizes my thoughts on this operator.
As a Node developer, I really see the usefulness of this operator in my day-to-day work because of JavaScript’s particularities, but in the context of Python I have mixed feelings.
Python’s data model is stricter and the built-in attribute lookup and collection traversal make no assumptions. An attribute/item exists or not and any exceptions must be explicitly handled or suppressed with one of the safe “getters”, such as getattr() and dict.get() that you mentioned.
A separate comment I would like to make is that when I see repeated or long/deep optional chaining expressions in the middle of business logic, that portion of code is a potential block to be refactored and/or the data structures may need to be revised, or perhaps that it is worth including a parsing/validation/transformation step to isolate or reduce the need for later checks.
It’s too easy/tempting to keep adding ?. and performing nullish coalescing to save time, until these things start piling up and you notice that half of an object structure is being tested attribute by attribute. Of course, there are scenarios where there is no escape, but indiscriminate use can make code a burden to read and interpret.