0

I'm trying to understand this question and answers:

python function default parameter is evaluated only once?

in order to understand it i try:

def f1(a, L=[]):
    if not L:
        print "L is empty"
        L = []
    L.append(a)
    return L

>>>f1(1)
L is empty
[1]
>>>f1(1)
L is empty
[1]

def f2(a, L=[]):
        if L:
            print "L isn't empty"
            L = []
        L.append(a)
        return L

>>>f2(1)
[1]
>>>f2(1)
L isn't empty
[1]

So I think in the case of f1 L is becoming empty again every time - it is assigned to [] again after every call of f1. But in case of f2 L is somehow isn't empty? Why?

Community
  • 1
  • 1
Alexey
  • 1,366
  • 1
  • 13
  • 33

1 Answers1

6

When you do this:

L = []

...you don't change the value referenced by L; you change the reference L to point to a brand new list [].

If you want to empty the list referenced by L without changing the reference itself, you can write:

del L[:]

...or use methods such as remove or pop that work by changing the current list.


Here's f1 and f2 in animated form to help you understand. (Click for webm. Wait for each gif to fade to white. The gifs don't sync up, sorry.)

f1

f2

Community
  • 1
  • 1
badp
  • 11,409
  • 3
  • 61
  • 89
  • Can you explain why in case of `f2` i've got non empty list, but in case of `f1` it's always emplty though code in both functions is similar? – Alexey Jan 17 '15 at 21:56
  • 1
    @user3572950 in `f1(x)`, `L=[]`, thus you run the `if not L` branch, which discards the `L` reference, so next time you run `f1(y)`, it'll still start with `L=[]`. When you call `f2(x)` the first time, `L=[]`, so you skip the `if L` branch and go straight to changing `L` with `L.append`. When you then call `f2(y)`, `L=[x]`, so you go through the `if L` branch (and discard the `L` reference). – badp Jan 18 '15 at 08:55
  • 1
    @user yep, that's it: when you assign to L you assign a new value to the reference L without affecting the previous value. Consider this: `A=B=[]; A.append(0); print A, B; A=[]; A.append(1); B.append(2); print A, B;` this should give `[0] [0]` `[1] [0, 2]` – badp Jan 22 '15 at 20:41
  • Maybe I'm starting to understand - there are two "versions" of `L` in each function - one "version" is default variable, evaluated only once, and other "version" - new list, that i'm creating inside `if` statement as you said **you change the reference L to point to a brand new list []** But it's unclear to me why **So next time you run f1(y), it'll still start with L=[]** By this time, when i run `f1` second time there are two "versions" of L - one is equal `[]` and another is equal `[1]` , so how can `if` statement understand what "version" of `L` it should use? – Alexey Jan 22 '15 at 20:49
  • @gr4k [Maybe a moving picture is worth a thousand words. (Fixed 2)](https://gfycat.com/PlasticCooperativeBubblefish) – badp Jan 22 '15 at 22:17
  • @gr4k [Here's `f2` as well for completeness and clarity.](https://gfycat.com/RapidKindKomododragon) – badp Jan 22 '15 at 22:49