-4

For example,

def function(data=None):
    print(data,id(data))
    if data is None:
        data=[]
    print(data,id(data))

    data.append(1)
    print("==================")

function()
function()

>> None 1781798096
[] 1780266168520
==================
None 1781798096
[] 1780266174856
==================

At the first execution of function(), variable data refers to a "None" object(id:1781798096) By third line of the code, now data refers to an empty list object(id:1780266168520) At second execution of function, data is expected to have the id value 1780266168520. But surprisingly, it gives out 1781798096 which is the same value when data referred to the "None" object.

But if we change default parameter to some arbitrary list, say [0],

[0] 1780266149960
[0] 1780266149960
==================
[0, 1] 1780266149960
[0, 1] 1780266149960
==================

we find out that it gives identical id values.

So my question is why can't we modify a variable which previously referred to "None" object and why does such difference occur if we set default parameter to "None" and [0]?

cs95
  • 379,657
  • 97
  • 704
  • 746
Jin
  • 1,902
  • 3
  • 15
  • 26
  • 1
    Your question makes no sense. Are you asking why local variables don't keep their values across function calls? – melpomene Aug 26 '17 at 07:14
  • @melpomene if you change default parameter to some arbitrary list, you will find out that the id values are exactly same. Why does such difference occur when you set default parameter to "None"? – Jin Aug 26 '17 at 07:16
  • I don't understand what you're talking about. – melpomene Aug 26 '17 at 07:17
  • 1
    `data` is a local variable that remains in scope only for a _single_ function call; it is not remembered from any previous function calls. Remember that `id(None)` will always return the same ID for the entire Python session, and any variable that is assigned to `None` will also have that same ID. – 101 Aug 26 '17 at 07:20
  • If you use `[0]` as the default, `if data is None` is never true, so you never assign anything else to `data`. Thus `data` always refers to the same object. – melpomene Aug 26 '17 at 07:22
  • You're getting confused because you're using a list as a default function argument, which is a bit of a special case in Python. In this case the list object is the _same_ across multiple function calls! See this question: https://stackoverflow.com/questions/1132941/least-astonishment-and-the-mutable-default-argument. A better demo for you would be to have a default argument as e.g. a string, which will result in a new object each function call. – 101 Aug 26 '17 at 07:43

3 Answers3

3

If you're asking why data's id value is the same initially, then that's because the default argument is initialised once when the function is defined, and remains throughout the program. That's also the reason for the "Least Astonishment" and the Mutable Default Argument.

When data is reassigned, all that happens is that it points to a new object (the empty list), and this object may or may not have the same id (REPL sessions frequently reuse the same ids of garbage collected variables).

cs95
  • 379,657
  • 97
  • 704
  • 746
  • When `data` is reassigned, it points to a new object([]). So I guess `data` no longer points to 'None', isn't it? – Jin Aug 26 '17 at 07:37
  • @Jin You're right, it points to a different `[]` after each assignment. – cs95 Aug 26 '17 at 07:38
  • @COLDSPEED then if it points to [], not to "None", why does `data`'s id value is the same as id value of "None" after second execution of `function`? – Jin Aug 26 '17 at 07:45
  • @Jin Because `data is not None`, so `data` is not reassigned, so all you do is append to the same list. See https://stackoverflow.com/questions/1132941/least-astonishment-and-the-mutable-default-argument – cs95 Aug 26 '17 at 07:46
0

None is a singleton object, so you should not create multiple object of NoneType. (Note that, you can create multiple object of singleton class). In python you don't always mutate the value which it holds, you call method on object, modify it or create new object and assign reference to the variable. Previously it was holding the reference to None object, when you changed it, its holding reference to other object. Same when you again assigned None , python initialized reference value with reference of None.

NishanthSpShetty
  • 661
  • 5
  • 14
0

You call function with no argument, so the it is set to None when entering function(). When you want to retain values of data, you need to return the data variable and then pass it to function() in the second call.

Juergen
  • 69
  • 5