1

I am experiencing a strange behavior of a built-in function locals() in Python. It is hard to explain exactly, but please take a look at a code:

def Main():
  def F(l=locals()):  print 'F', id(l), l
  a= 100
  F()
  print '1', id(locals()), locals()
  F()

In the local function F, I am assigning locals() into l as a default value for enclosure. Since locals() is a dict, its reference is copied to l. So the last three lines should have the same result.

However the result is like this:

F 139885919456064 {}
1 139885919456064 {'a': 100, 'F': <function F at 0x7f39ba8969b0>}
F 139885919456064 {'a': 100, 'F': <function F at 0x7f39ba8969b0>}

The three print statements are called at almost the same time, and id of locals() and l are the same, but the first l used in F does not have content.

I cannot understand why this happened. Can anyone explain this phenomenon? Or is this a known/unknown bug?

Many thanks!

Akihiko
  • 362
  • 3
  • 14
  • Possible duplicate of [Why are default arguments evaluated at definition time in Python?](http://stackoverflow.com/questions/1651154/why-are-default-arguments-evaluated-at-definition-time-in-python) – Tadhg McDonald-Jensen May 19 '17 at 17:35
  • No, it doesn't explain this phenomenon. It is expected that ``l`` in ``F`` and ``locals()`` have the same id, but it is NOT expected that they do not have the same content. – Akihiko May 19 '17 at 17:38
  • if you call `locals()` inside of `F` you'd get a different result, but since all three calls to `locals()` is inside `Main` (because the definition is inside Main so the default argument is evaluated in that scope) They give the same dictionary – Tadhg McDonald-Jensen May 19 '17 at 17:39
  • They are actually the same dictionary as their ids are the same. However their contents are different. That is the issue I cannot understand. – Akihiko May 19 '17 at 17:41
  • ok sorry for the confusion, you can get the same behaviour by just doing `saved = locals()` and printing it out later, no need to also add extra contexts to confuse (me) people. Retracting my close vote. – Tadhg McDonald-Jensen May 19 '17 at 17:53
  • No problem. Thanks for commenting. – Akihiko May 19 '17 at 18:09

1 Answers1

4

If you read the docs for the locals function, you'll see

Update and return a dictionary representing the current local symbol table. Free variables are returned by locals() when it is called in function blocks, but not in class blocks.

locals() doesn't just return a dict of local variables; it also updates the dict to reflect current local variable values.

user2357112
  • 260,549
  • 28
  • 431
  • 505
  • Now I clearly understand the above behavior. I thought that similar to ``globals``, ``locals`` provides us a direct access to the dictionary of local variables. Is there an alternative to directly access to the dictionary of local variables in a function? – Akihiko May 19 '17 at 17:55
  • 2
    @Akihiko: Local variables aren't actually implemented with a dict, so no. – user2357112 May 19 '17 at 17:56