8 ms·
Ouch, that is one extremely non-user friendly feature going on there. The only reason it works at all is because most people use default for strings/numbers onl
by RyanZAG 13y ago
Ouch, that is one extremely non-user friendly feature going on there. The only reason it works at all is because most people use default for strings/numbers only.
That functionality really should be changed for the next major python release, and have default evaluate each time the function is called - which is how 99.9% of people using it expect it to work.
- mickeyp 13y agoYou don't change behaviour like that once it's been introduced. That will just break existing code in very subtle ways. There's plenty of code out there that rely on default values being assigned a mutable value and changing it -- even in a major point release -- would be far worse off. Python's been around for 20 years; it's too late to make a change like that. It IS a "wart" in that you need to be aware of it to know that it's an issue, but once you are, it is an obvious thing to spot.
- Camillo 13y agoThey made other compatibility-breaking changes in Python 3, though. It'd be interesting to know why this particular feature was kept. I guess from another point of view it's simpler to have everything in the `def` line executed when that line is reached (which is when the function is defined).
- mixmastamyk 13y agoI don't know. Scripts have to be somewhat rewritten in Py 3 anyway, I think it would have been a good time to fix it.
- rmc 13y agoPython 3 is deliberately not backwards compatible. They made several big breaking changes to remove warts.
- spamizbad 13y ago> That functionality really should be changed for the next major python release Make lists immutable you mean? Like tuple()? Edit: Or force re-evaluation on every function call (could be pretty slow)? The best practice is to just use a tuple (immutable) instead of a list to begin with. You can always do mylist = list(defaulttuple) inside your function first thing if you really want to work with it as a list. Also, both pylint and pep8, two python static analyzers, will all warn you about any mutable default arguments you provide. Many Python developers have these hooked into their editor or precommit hooks to catch things like this (among others).
- wahnfrieden 13y agoTuples shouldn't be differentiated from lists primarily in terms of mutable vs immutable. They represent different usages semantically, even though their primary functional difference is in their mutability. Lists are largely for homogeneous collections, whereas tuples are heterogeneous. When you mix them, you abuse what they signal to the reader. Python doesn't do much for type safety. Either accept the pitfalls of mutability as a tradeoff, or subclass list to make a safer type.
- spamizbad 13y agoThat's actually super insightful (homogeneous vs heterogeneous). I never made that connection but looking back I see it everywhere in Python code, and even did it unknowingly myself.
- klibertp 13y agoWhy didn't you use an array (from array module in stdlib) for homogeneous collection then? Python is dynamically typed, which means that, by default, we assume different types everywhere (heterogeneity). If you want to express homogeneity just do so explicitly.
- Myrmornis 13y agoNo, spamizbad is correct that wahnfrieden's comment was insightful. List and tuple have totally different semantics; they also happen to differ in mutability which just confuses the issue unfortunately.
- klibertp 13y agoI'm not that sure about "totally different" semantics; in Python lists and tuples happen to share quite a lot of public interface. As they both are heterogeneous by default (in Python), I disagree with this being their biggest difference. It's not a case in OCaml or Erlang, where lists and tuples differ significantly in both interface and complexity of basic actions. For example, what is a computational complexity of getting nth element of tuple and list in Python, and why it's exactly the same for both of them? In Erlang, where lists are real lists, getting nth element is O(n) in case of lists and O(1) in case of tuples. In Python, lists and tuples mean almost exactly the same thing. That's how Python is implemented. Those two things have "totally different" semantics in many other languages, not so in Python. As so, using the one over the other in many cases is purely stylistic matter, not the matter of semantics... unless it's about mutability, of course. If they're as different as you and grandparent suggest, then please list those differences, and mean in Python. As I said, in OCaml Lists and tuples are completely different types, starting with the fact that tuples are not iterables (!). The same is true in Erlang, where you need to explicitly convert a tuple to list to get all the elements of a tuple. Both list and tuple are iterable in Python, however. I just see much more similarities between lists and tuples in Python than differences, to the point that I wouldn't mind calling tuples an immutable_list or frozenlist, or something like that.
- bluecalm 13y agoThere are actual reasons to make it and keep it that way. Easy caching function's results is one. You may want to read this SO thread: http://stackoverflow.com/questions/1132941/least-astonishment-in-python-the-mutable-default-argument http://stackoverflow.com/questions/1132941/least-astonishmen...
- Tloewald 13y agoThe accepted explanation seems wrong to me. Whether or not functions are first class objects or not, the behavior of def is a matter of design choice and in this case the wrong choice has been made. All the rationales are broken -- they're uncommon use cases and perfectly easy to implement without the behavior, i like Python but this is a wart.
- njharman 13y agoNo.
- the1 13y agono, default parameter should not be evaluated every time the function gets called. current behavior is totally fine. it is well defined that somelist.append(x) appends x to somelist inplace.