开发者

In Python, why is list[] automatically global? [duplicate]

开发者 https://www.devze.com 2023-03-12 18:32 出处:网络
This question already has answers here: Why isn't the 'global' keyword needed to access a global variable?
This question already has answers here: Why isn't the 'global' keyword needed to access a global variable? (11 answers) Closed 6 months ago.

This is a weird behavior.

Try this :

rep_i=0
print "rep_i is" , rep_i
def test():
  global rep_i #without Global this gives error but list , dict , and others don't
  if rep_i==0:
    print "Testing Integer %s" % rep_i
    rep_i=1
  return "Done"

rep_lst=[1,2,3]
 

def test2():
  if rep_lst[0]==1:
    print &q开发者_如何学Gouot;Testing List %s" % rep_lst
  return "Done"


if __name__=="__main__":
  test()
  test2()

Why list do not need to declare global? are they automatically global?

I find it really weird, I use list most of the time and I don't even use global at all to us them as global...


It isn't automatically global.

However, there's a difference between rep_i=1 and rep_lst[0]=1 - the former rebinds the name rep_i, so global is needed to prevent creation of a local slot of the same name. In the latter case, you're just modifying an existing, global object, which is found by regular name lookup (changing a list entry is like calling a member function on the list, it's not a name rebinding).

To test it out, try assigning rep_lst=[] in test2 (i.e. set it to a fresh list). Unless you declare rep_lst global, the effects won't be visible outside test2 because a local slot of the same name is created and shadows the global slot.


You only need to use global if you are assigning to the global name. Without global, an assignment creates a new local.

There's nothing special about how global applies to a list—global simply influences scope and name resolution.


There is an error in python called UnboundLocalError which often confuses newcomers. The confusing thing is: future assignment does change the way a variable is looked up.

When the interpreter sees a variable name for the first time, it looks ahead to the end of current code block, and if you don't have an assignment to it anywhere within the same block of code, the interpreter considers it global. If you do, however, then it is considered local, and any reference to it before assignment generates an UnboundLocalError. That's the error you got. That's why you need to declare global rep_i. If you did not assign rep_i, you wouldn't need this line.

Also, this has nothing to do with variable type. Also, assigning or appending an item to the list (which you probably meant to do, but did not) is not assignment of the list itself, it is essentially calling a method on a list object, which is different from assignment: assignment creates a new object (possibly under a name that already exists), while manipulating a list just changes an existing list. You can try:

In [1]: # It won't work with small integers, as they are cached singletons in CPython

In [2]: a = 123123

In [3]: id (a)
Out[3]: 9116848

In [4]: a = 123123

In [5]: id(a)
Out[5]: 9116740

In [6]: # See, it changed

In [7]: # Now with lists

In [8]: l = [1,2,3]

In [9]: id(l)
Out[9]: 19885792

In [10]: l[1] = 2

In [11]: id(l)
Out[11]: 19885792

In [12]: # See, it is the same

In [13]: # But if i reassign the list, even to the same value

In [14]: l = [2,2,3]

In [15]: id(l)
Out[15]: 19884272


Here's an example that demonstrates that a non list/dict variable is available in a subroutine, and the problem is, as everyone says, the act of rebinding in your original code sample:

x = 1
def test():
    y = x + 1
    print y
test()

You'll see this prints out 2, despite x not being declared global.


If you had assigned a new value to rep_lst inside of test2 (not just to one of its elements, as you did) it would not work without the global flag. In Python, if you do not assign to a variable inside a function it will look for that variable in in more global scopes until it finds it.

For example, in this code segment I define the list both globally and inside of example(). Since the variable in example() is closer in scope to example2() than the global one is, it is what will be used.

x = ["out"]

def example():
    x = ["in"]
    def example2():
        print x # will print ["in"]

This has nothing to do with lists, but is the behaviour of any variable in Python.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号