Functions in most popular languages behave this way. `get` is just a method; its arguments will never be short-circuited. If you wanted short-circuiting, use the ternary operator:
my_dict['existing_key'] if 'existing_key' in my_dict else foo()
You could also define a `get_lazy` method that does the above, taking a nullary function as its key and evaluating it if the key is missing. But then you would need to wrap your default values in a lambda, which would look absurd for the common use case of calling `get` with some constant default value. Seems unnecessary when the ternary operator works fine.
If I know my_dict doesn't hold values that that are false-like, e.g. 0 or [], I use `or` to lazily alternate between options. This works because in python, `or` returns the first value that has a truthy value. In this case it would be
my_dict.get('existing_key') or foo()
This would also easily let you do multiple alternations (much more annoying with the ternary operator).
gp's approach works best when you know that the argument is a list or tuple (something which can be empty). Of course, due to python's lack of typing, you should only use that approach when the function is being used in well-understood contexts.
Python is generally terrible at providing immutable types and workflows. No such thing as a constant, class variables are mutable by default, no built-in immutable dictionary class, etc.
I use a linter to catch this sort of thing and subclass `collections.namedtuple(...)` whenever I need to at least try to abolish mutability. It's one of the worst things about the language.
[edit] You can argue that there would be use cases for mutable defaults, and as with any edge use case you'd be right in asserting its existence. Unfortunately, I can't think of any solution (typing, changing function argument evaluation rules, etc) that wouldn't fundamentally change the language and break just about every sizable python library in existence. This looseness is baked deep into the language as far as I can see.
1) aren't there specific immutable pass-by-value forms in python? If you pass a default integer, for example, and change the value of that variable in the function body, the next call will respect the default parameter and not the mutated parameter.
I would argue that that is an edge case that should be done with decorators. The whole mutable default thing bites everyone at least once, and at best it just means more code to do the same thing.