Introduction to the scope rules and closures in Python, and introduction to python

Source: Internet
Author: User
Tags builtin

Introduction to the scope rules and closures in Python, and introduction to python

Before performing a simple analysis on the closures in Python, let's take a look at the scope rules in Python. For details about the scope in Python, many blog posts have been introduced. Here we will start with a simple example.

Scope in Python

Assume that the following functions are defined in the interactive command line:

>>> a = 1>>> def foo():    b = 2    c = 3    print "locals: %s" % locals()    return "result: %d" % (a + b +c)>>> a = 1>>> def foo():    b = 2    c = 3    print "locals: %s" % locals()    return "result: %d" % (a + b +c)

The above code first assigns a value of 1 to a, and then defines a function: foo (). In function foo (), we define two integers B and c. The return values of the function are the sum of numbers a, B, and c.

Verify the above functions:

# result>>> foo()locals: {'c': 3, 'b': 2}result: 6# result>>> foo()locals: {'c': 3, 'b': 2}result: 6

Based on the verification result, the return value of the foo () function is 6. In the preceding function definition, only values of B and c are assigned. How does one call a function to determine the value of? This involves the function scope rules. This article excerpts the related discussion in the Python Reference Manual (version 4th:

Each time a function is executed, a local namespace is created. This namespace represents a local environment, including the name of the function parameter and the variable name assigned to the function body. When resolving these names:

The interpreter will first search for a local namespace;

If no matched name is found, it searches for the global namespace (the global namespace of the function is always the module that defines the function );

If the interpreter cannot find the matching value in the global namespace, the built-in namespace will be checked;

If no matching value is found in the built-in namespace, A NameError exception occurs.

In the preceding example, the foo function first finds the matching values of the three variables in the local namespace. The locals () method in the above Code provides the content of the partial namespace of the foo function. It can be seen that the local namespace is a dictionary that contains the values of B and c, because these two variables are defined in the foo function. However, the local namespace does not contain the value of a, so you need to search for it in the global namespace. You can use _ globals _ to obtain the local namespace of a function.

# The global namespace of the foo function >>> foo. _ globals __{ 'A': 1, '_ builtins _': <module '_ builtin _' (built-in)>, '_ package _': None, '_ name _': '_ main _', 'foo': <function foo at 0x0000000004613518>, '_ doc _': None} # global namespace of the foo function >>> foo. _ globals __{ 'A': 1, '_ builtins _': <module '_ builtin _' (built-in)>, '_ package _': None, '_ name _': '_ main _', 'foo': <function foo at 0x0000000004613518>, '_ doc _': None}

The global namespace of the foo function contains the built-in function module, foo function, variable a, and other parameters. Since variable a is found in the global namespace of the foo function, the foo function returns the sum of the three variables.

Python Closure

The above Python scope rules are universal. However, in Python, "Everything is an object", and functions are no exception. This means that the function can be passed to other functions as a parameter, stored in a data structure, or returned as a function. In this case, what changes will happen to the scope rules of Python? Let's take an example:

>>> def foo():    a = 1    def bar():      b = 2      c = 3      return a + b + c    return bar>>> def foo():    a = 1    def bar():      b = 2      c = 3      return a + b + c    return bar

In this example, we define a function foo and assign values to variable. However, unlike the previous example, in function foo, a function bar is nested and two variables are defined. This function is used as the return value of function foo. According to the preceding scope rules, the partial scope of function foo is neither the local scope of function bar nor its global scope. can function bar correctly match the value of variable? Let's verify whether this function can run normally.

# Call function foo () >>> bar = foo () # Return Value bar is a function >>> bar <function bar at 0x00000000045F3588 ># call bar () >>> bar () # The result is 6 of the sum of the three variables.

The above verification results indicate that in the nested functions above, internal functions can correctly reference the variables of external functions, even if the external functions have already been returned.

The behavior of variables in the local scope of the internal function that can access the local scope of the external function is called closure. The feature that internal functions can access external function variables is similar to directly "package" external function variables into internal functions. We can also understand the closure as follows: the object obtained when the statements that constitute the function and the environment for executing these statements are "packaged" is called a closure.

Several objects related to closures
To understand how a closure can reference external function variables, we also need to introduce several objects related to the closure. These objects involve the underlying implementation of Python, which is not described in this article. You can refer to the following articles:

However, to intuitively describe the implementation process of the closure (without analyzing the underlying implementation), the following code object is briefly introduced here. A code object is a code object that indicates the executable Python code or bytecode compiled into bytes. It has several important attributes:

Co_name: function name
Co_nlocals: number of local variables used by the function
Co_varnames: a tuple containing the name of a local variable
Co_cellvars: A tuples that contain the names of local variables referenced by nested Functions
Co_freevars: A tuples that store variable names in the outer scope used
Co_consts: A literal tuples containing bytecode

Among them, the key is the co_varnames and co_freevars attributes. We can slightly modify the above example:

Python

>>> Def foo (): a = 1 B = 2 def bar (): return a + 1 def bar2 (): return B + 2 return bar >>bar = foo () # outer function >>> foo. func_code.co_cellvars ('A', 'B') >>> foo. func_code.co_freevars () # Inner nested functions> bar. func_code.co_cellvars ()> bar. func_code.co_freevars ('A',) >>> def foo (): a = 1 B = 2 def bar (): return a + 1 def bar2 (): return B + 2 return bar >>bar = foo () # outer function >>> foo. func_code.co_cellvars ('A', 'B') >>> foo. func_code.co_freevars () # Inner nested functions> bar. func_code.co_cellvars ()> bar. func_code.co_freevars ('A ',)

The preceding description shows that co_cellvars of the code object of the outer function stores the name of the variable to be referenced by the nested function, the co_freevars of the code object of the nested function in the inner layer saves the variable name that needs to reference the scope of the external function. Specifically, the foo function is nested with two functions, both of which must reference the variables in the partial scope of the foo function. Therefore, foo. func_code.co_cellvars contains the names of variables a and B. The function bar is the return value of foo and only references variable a. Therefore, bar. func_code.co_freevars only contains variable.

The correspondence between internal functions and external functions co_freevars and co_cellvars, in this way, the internal function has a special attribute _ closure _ of the closure during the function compilation process (this is implemented at the underlying layer ). The _ closure _ attribute is a tuples composed of cell objects and contains variables referenced by Multiple scopes. You can perform the following verification:

>>> Foo. _ closure _ # None # reference of the internal function bar to variable a >>> bar. _ closure _ (<cell at 0x00000000044F6798: int object at 0x0000000003FA4B38>,) # value of variable a referenced by the internal function bar> bar. _ closure _ [0]. cell_contents1

This article briefly explains the closure of PYTHON and the basic knowledge of the scope. If you want to learn more, please query the scope rules and closure details in Python on this site.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.