On 25/11/2015 10:52, Steven D'Aprano wrote:
On Wed, 25 Nov 2015 07:14 pm, Antoon Pardon wrote:

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.

What do you think most people would expect to happen here? I know, because you gave a spoiler, that it loops forever, otherwise I wouldn't be sure /without trying it/ (but I tried it anyway).

Here's the same code in a somewhat different language:

L := (1,2)
for i in L do
|   L append:= i
|   println L
od

And this is the output:

(1,2,1)
(1,2,1,2)

Which output (infinite series of [1,2,1,2,1,....] or the above) is more sensible, and which do you think people might prefer?

The point is that the behaviour of the loop is by no means obvious, so neither is the behaviour of the function defaults.

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.

Accept that some things /are/ a source of confusion. When, in writing documentation, I find something hard to explain something, then I try and make it simpler in the program. But not enough of that goes on: it seems to be more lucrative to write thicker user manuals, and provide longer training courses, than to make software simpler.

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.

Sure. The problem is that it might not be obvious it's initialised once.

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.

The concept of variables doesn't take long to learn in an 'ordinary' language.

But one problem with Python is that it gives the impression that almost anything is possible. Your example can be made to work with a slight tweak:

 count = 1
 coin = lambda: random.choice(['heads', 'tails'])
 while coin() != 'heads':
      count += 1

In some languages, there would never be such a possibility because they don't have the extraordinary flexibility and dynamism of Python. But once you get the idea that the language can almost do magic, then it doesn't seem so far-fetched that you original example could work!

Just like functions. If you want code to run each time you call the
function, PUT IT INSIDE THE FUNCTION BODY.

Many languages don't have the concept of code running outside a function body. And especially they don't have the truly bizarre one that a function definition is itself a piece of code that is executed. Or maybe not executed, if it's inside a conditional statement! And therefore does not exist. This is an extra hurdle with learning or even using this language.

--
bartc
--
https://mail.python.org/mailman/listinfo/python-list

Reply via email to