On Wed, 25 Nov 2015 07:14 pm, Antoon Pardon wrote: > Op 20-11-15 om 01:33 schreef Steven D'Aprano: >> On Fri, 20 Nov 2015 07:57 am, Marko Rauhamaa wrote: >> >>> Laura Creighton <l...@openend.se>: >>> >>>> My experience says that the people who are confused want lists to >>>> behave like tuples. period. i.e. they don't want lists to be mutable. >>> I think it's simpler than that. When you have: >>> >>> def f(x=[]): >>> y = [] >>> >>> the first [] is evaluated when "def" is executed, while the latter [] is >>> evaluated whenever "f" is executed. It's easy to be confused. >> It shouldn't be. The function declaration >> >> def f(x=[]): >> >> is executed only once. The function body, conveniently indented to make >> it stand out: >> >> y = [] >> >> is executed every time you call the function. > > What exactly is your point?
That there is a simple analogy between the distinction between code inside/outside a for-loop, and code inside/outside a function. If you can understand why this loops forever, instead of just twice, then you can understand why function defaults work the way they do: L = [1, 2] for i in L: L.append(i) print(L) There is nothing "bizarre" or complicated or difficult to understand happening here. It might not be what you want to happen. It might not be what you expect to happen. But if you can't understand why it happens even after multiple explanations, then your learning skills are severely lacking. > People's confusions don't disappear > because you as an expert have a good understanding of what is > going on and so are no longer confused. I'm an expert? Awesome! No. But people's confusion would disappear if they would: - think about the process - try to follow the steps of what is happening - pay attention to the explanations given - and ask for clarification instead of arguing. I have come to the conclusion that there is nobody as stupid as an intelligent person who refuses to learn. I really don't know how more clear we can possibly be. If you take a list, initialised as the empty list ONCE, and then modify it repeatedly, the list doesn't magically become empty just because you want it to be empty. I completely understand beginners making this mistake: # Simulate tossing a coin until it is heads. count = 1 coin = random.choice(['heads', 'tails']) while coin != 'heads': count += 1 "Why does the loop run forever?" The coin doesn't magically toss itself, no matter how intuitively obvious it is that it should. (And I'm not making this example up -- I've seen three or four beginners make equivalent errors. It seems to be a very common conceptual mistake.) These beginners, at least, don't argue back that it is "bizarre" and stupid and crazy that you have to choose a new value for the coin variable each time through the loop. They soon learn that code outside the loop only runs once, if you want it to run each time through the loop, you should put it inside the body of the loop. Just like functions. If you want code to run each time you call the function, PUT IT INSIDE THE FUNCTION BODY. > Some aspects in the langauage are easily grasped and other > aspects tend to create confusion. You're right. Some aspects of the language are inherently confusing and hard to reason about. Threads are an example of that. The more powerful, and tricky, aspects of regular expressions. The weird stuff that happens during interpreter shutdown if you have __del__ methods in your objects. __del__ methods in general. There are many things which are hard to reason about, and therefore confusing. *This is not one of them.* This is not hard to reason about. The rules are no different from what happens in simple, ordinary code: L = [] # Initialise the list *once*. def func(): L.append(1) return L If I call func() three times, what value does it return? If you can get that, you can get this: def func(L=[]): # Initialise the list *once*. L.append(1) return L Confusing? Absolutely not. Or rather, if anyone cannot understand the behaviour of either function *after having it explained multiple times*, then programming is the wrong area for them. They should take up something more suited to their intellectual limitations, like dish washing, ditch digging, or politics. But is it predictable or intuitive? No, I agree, this behaviour is not intuitive, if you are coming from a background without equivalent rules. I will completely grant you that most people without Python experience would not correctly predict the behaviour of mutable defaults. I was caught out on that too, as I already admitted. Even though I already knew all the facts I needed to predict the behaviour correctly, I didn't put 2+2 together and get 4. That's *my bad*, not the language's fault. How much harder must it be for those who don't know the essential facts? I don't expect anyone to intuit the behaviour of Python defaults. That would be unreasonable. There's no shame in guessing wrong from a position of ignorance. Me, on the other hand... I should have known better. I did know better. But there's a big difference between those who guess wrong from a position of ignorance, and then make an honest attempt to understand the behaviour and why it actually does make sense and is even sometimes useful (even if they don't like it), and those people who insist that it is nonsensical, magical and "bizarre". -- Steven -- https://mail.python.org/mailman/listinfo/python-list