6 ms·
> 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 ev
by 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.
- Myrmornis 13y agoThis was best and most succinctly stated by wahnfrieden: tuples are appropriate where a named-tuple could also conceivably be used.
- snth 13y ago> Lists are largely for homogeneous collections, whereas tuples are heterogeneous. What? What makes you think that?
- Myrmornis 13y agoIt's a perfectly accurate statement. If a tuple is homogeneous, it's only because all of its slots happen to be for objects of the same type (e.g. a row of a database table all of whose columns are integers, or the arguments of a function which takes 3 integers as input). In contrast, homogeneous lists are the norm (other than mixing None with non-None values). When was the last time you needed a heterogeneous list?
- wahnfrieden 13y agoThe quote comes from Guido van Rossum almost verbatim so that may be a good place to start if you want to dig deeper. As I've also seen, a good rephrasing is that lists have order whereas tuples have structure. Yet another mnemonic I've heard that seems apt is that tuples are appropriate where a named-tuple could also conceivably be used.
- beambot 13y agoThat's crazy-interesting and seems like a very good rule of thumb. I've been using Python for a very long time and had never heard this. Why is it not in the PEP?!
- wahnfrieden 13y agoWhich PEP, PEP-8? That's only a style guide. It's included in the stdlib documentation on data structures: http://docs.python.org/2/tutorial/datastructures.html#tuples-and-sequences http://docs.python.org/2/tutorial/datastructures.html#tuples...
- dalke 13y agoThe quote is "Tuples are for heterogeneous data, list are for homogeneous data. Tuples are not read-only lists." Guido van Rossum March 12, 2003 in python-dev. However, don’t treat Guido’s statement as a mandate! "Yes, taking Guido too seriously can have that effect on people <1.1 wink> The trick is in knowing when Guido is proscribing dogmatic law, and when he is describing his intent when he designed feature(tte)s of Python, or his point of view at this moment, or how he wished people would see it, or reacting to what he had for lunch. He's just human, you know, and no more infallible than the best of us." Thomas Wouters March 12, 2003 in python-dev For example, consider object.__class__.__bases__. That's a tuple of homogenous data. It's not of a fixed length, and the base class at a given position has no intrinsic name, other than "first", "second", etc. Do you think the use of tuple here is a bug? Should it be a list instead?
- Myrmornis 13y ago> Tuples shouldn't be differentiated from lists primarily in terms of mutable vs immutable. This. In particular, tuples are for collections whose length is fixed and meaningful, and for which you could give names to each field. Lists are for collections whose length doesn't correspond to anything in particular and which you could imagine growing and shrinking. As an aside, django makes this mistake and confuses people: using tuples where semantically they should be lists, presumably out of a desire for immutability.
- dalke 13y agoA class's __bases__ is a tuple of base classes. The length is not fixed, and there's no special name for [i] other than (i+1)-th; only its ordering is important. Do believe that the use of a tuple here is a bug, like you do for Django? The __bases__ can be re-assigned. Assignment to an instance is guaranteed atomic in Python. Some of the list operations are not. Thread-safe guarantees might be another reason for restricting list's mutability.
- wahnfrieden 13y agoYou're right, at a certain point functionality and other characteristics make all the difference. It's just a generality for higher-level code I suppose.
- shadowfox 13y agoThis is pretty valid. It is probably also true (generally speaking) that people tend to use lists when the cardinality is not fixed and tuples otherwise.
- Myrmornis 13y ago> The best practice is to just use a tuple (immutable) instead of a list to begin with. No, that's not good advice. Tuples are not just immutable lists. See below.
- RyanZAG 13y agoNo, the list issue is the smaller problem here, imo. The big problem is the example given at the bottom of the page. def print_now(now=time.time()): print now The expectation here is that it will give the current time as the default, but the expectation is broken by the very unexpected behavior of the language. That's the kind of thing you want to avoid if at all possible. I see no reason why anybody would not want the default to evaluate every time - tiny bit of speed seems like a very premature optimization here. If you're worried about speed, you could make a class/instance variable, and then set the default to that variable. That's what 'default' is actually doing in the current implementation - and it sounds unexpected in the extreme.
- mhurron 13y agoIt's only unexpected if you didn't learn when Python instantiates default variables and how it passes them. Or put another way, if you treat Python like some other language you learned, apparently not realizing it is a different language. Now personally I hardly every use default values, but to me, when I see this - > I see no reason why anybody would not want the default to evaluate every time It means you should have put it in the method.
- altcognito 13y ago> Or put another way, if you treat Python like some other language you learned, apparently not realizing it is a different language. No, it's not "some other language", it's every other language. Why? Because the behavior being described isn't really a default. It's more like a static variable.
- RyanZAG 13y agoI want to create a function that tells me the temperature - but also lets me know the temperature yesterday. Clearly, the best way for this function to work is to have a default value of the current time. Python default values simply won't work here, as the time will be when I first start the program up and not when I call the function tomorrow for the current temperature. Why would I ever want to have the value from when I first launched the program?! Your argument that "this is how python does it" is not a very good one. Why should I have put it in the method? I want a default value! The reason for having the default value on a function in the first place is to allow me to make functions work with a default value. If this doesn't work, the feature is useless. As I said in the first post, the only reason the feature is usable at all is because, luckily, people nearly always use only numbers or strings for default values. EDIT: Plus your observation that you rarely use default values is probably for a good reason: they don't really work. Maybe if they worked, you'd use them?