Changing list items and changing the list itself

I have a question about variable scope, I tried to find an answer here and I have a similar but still a bit confusing here Function changelog values, not variable values ​​in Python

So the code looks like this:

position = [50, 50]

# Handler for timer
def tick():
    x = random.randrange(0, width)
    y = random.randrange(0, height)
    position[0] = x
    position[1] = y

      

Is that why I don't need to add a "global position" to change the variable position elements?

+3


source to share


3 answers


The addition global position

would only be necessary if you assigned a global position variable to reference the new list (without a global declaration, the position will be written to the locals for this function).

In your situation, all you do is search for the position of the global variable to find the list it refers to. Then you update this list in place.



Here is a Python mentor visualization that displays all the options (assign to local, assign to global, update the list referenced by the global).

Also, take a look at Ned Batchelder's excellent blog post that fully explains the python-pass-by-object pass mechanism.

+1


source


From the documentation about names and bindings -

If a variable is used in a code block but is not defined there , it is a free variable.

From the global operator documentation -

A global statement is a declaration that is executed for the entire current block of code. This means that the listed identifiers must be interpreted as global. It is not possible to assign a global variable without globals, although free variables can refer to global variables without being declared global.

(Emphasis mine)

When you do -

position[0] = <something>

      

You are not defining anything, you are mutating an already defined position

inplace list (by changing its 0th element to refer to something else).

Suppose if it has position

n't been defined ever when you do something like



position[0] = 1

      

You will receive NameError

-

>>> position[0] = 1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'position' is not defined

      

This is why, in spite of what you do postion[0] = <something>

, its still a free variable, as it is not defined in the block and therefore is treated as global.


UPDATE :

Additional information when you do -

position[0] = <something>

      

This is not a simple statementassignment

, its actually an extended assignment operator .

+1


source


You need to apply two concepts to understand the code

  • Python Object Model
  • Scoping

First, the Scope Rules:

Following is the hierarchy of variable definition rules for variables

  • Local scope - inside a function
  • Enclosing - inside any or all of the closing function
  • Global - top level module (file)
  • Built-in - any built-in modules that are imported

Python Object Model:

In Python, everything is an object. When the say variable is declared x = 1000

, the following steps are performed

  • An int object with the value 1000 is created
  • object reference created x

  • x

    points to this integer object

Now, when the statement position[0] = x

is executed internally tick()

, the statement has no purpose only for initialization. Since position

it is not defined within the scope of a function, it searches in the order of the hierarchy of scoping rules - scope (parent function) followed by Scope module (file) followed by BuiltIn modules. Here it finds the variable in the global scope and updates it.

In case your statement is position = [100, 100]

, a new list object is created and a new object reference is created within the scope of tick () and does the assignment

If you have a statement global position

, it tells Python that the variable in the Global Scope is the same as the variable in the Local Scope. It then position = [100,100]

creates a list object [100,100]

and binds its global variable position

to the new list object.

+1


source







All Articles