function mechanism of Python virtual machine (iii)

Source: Internet
Author: User

Parameter categories

In the two chapters of the function mechanism (a) and the Python virtual machine function mechanism (ii) of the Python virtual machine, we pyfunctionobject the namespace of the object and function execution respectively. In this chapter, we will analyze the implementation of function parameters.

In Python, the parameters of a function can be divided into four categories depending on the situation:

    • Positional parameters: such as f (A, b), A and B are called positional parameters
    • Key parameters: F (A, B, name= "Python"), where the name= "Python" is called the key parameter
    • Extended position parameters: F (A, B, *args), where *args is called extended position parameter
    • Extension key parameters: F (A, B, **kwargs), where **kwargs is called an extension key parameter

When the function is called through the call_function instruction, and call_function is the function of call_function through the function to complete the call. Before parsing the parameterless function call, we have entered into the Call_function function, this time, we want to parse the function of the call, still go back to the Call_function function

Ceval.c

Static Pyobject * Call_function (pyobject ***pp_stack, int oparg) {//[1]: processing function parameter information int na = Oparg & 0xff;int nk = (Oparg & Gt;> 8) & 0xff;int n = Na + 2 * nk;//[2]: Get Pyfunctionobject object Pyobject **pfunc = (*pp_stack)-n-1; Pyobject *func = *pfunc, ...}

  

When the Python function starts executing the call_function instruction, it first obtains a directive parameter oparg. In this directive parameter Oparg, the actual record is the number of function parameters information, including the number of positional parameters and the number of key parameters. Although the extended position parameter and the extension key parameter are more advanced forms of positional and key parameters, the extended positional parameters are essentially composed of multiple positional parameters. This means that although there are four types of parameters in Python, in fact we only need to record the number of positional parameters and the number of key parameters, you can know how many parameters, altogether need to how much memory space to maintain the parameters

The length of the call_function instruction parameter is two bytes, in low byte, the number of positional parameters is recorded, in high Byte, the number of key parameters is recorded. Because, in theory, a function in Python can only have 256 positional parameters and 256 key parameters

From call_function we can see that NA is actually the number of positional parameters, and NK is the number of key parameters. Now, let's revise the source code of Call_function to see how Na and NK are in functions with different kinds of parameters. While outputting na and NK, we also output two parameter-related information maintained in the Pycodeobject object of the function: Co_argcount (the number of positional parameters for the Code block, such as the number of positional parameters of a function) and co_ Nlocals (number of local variables in the Code block, including the number of positional parameters)

Here is a question, since co_nlocals contains the number of local variables, and the number of function position parameters, that Co_argcount is not superfluous it? In fact, in Python, the function parameters are very closely related to the local variables of the function, in a sense, the function parameters are a function local variable, they are placed in memory continuously. When Python needs to request a memory space for a function to hold local variables, it needs to know the total number of local variables by co_nlocals. Therefore, you can request memory space for a parameter only if the number of parameters is included in the co_nlocals. Although Co_nlocals contains the number of arguments, there is no way to know the number of arguments, so there must be a co_argcount that tells the Python function how many arguments there are. Is it a little dizzy? That's okay, let's change the Call_function method to see the difference between the function parameter and the local variable and the relation

Ceval.c

Static Pyobject * Call_function (pyobject ***pp_stack, int oparg) {int na = oparg & 0xff;int nk = (oparg>>8) & 0xff;int n = Na + 2 * NK; Pyobject **pfunc = (*pp_stack)-n-1; Pyobject *func = *pfunc; Pyobject *x, *w;char *func_name = Pyeval_getfuncname (func), if (strcmp (Func_name, "py_func") = = 0) {printf ("[Call_ function]:na=%d, nk=%d, n=%d\n ", Na, NK, N); Pycodeobject *co = (Pycodeobject *) Pyfunction_get_code (func);p rintf ("[Call_function]:co->co_argcount=%d, Co-> Co_nlocals=%d\n ", Co->co_argcount, co->co_nlocals);} ......}

  

As shown in the preceding code, parameter information is printed only when the function name is Py_func. After compiling the run, we'll take the fancy toss py_func this function

Def Py_func (A, B):    Pass

  

1. Position parameters

Py_func (1, 2)//bytecode instruction 9 load_name                0 (py_func) load_const               1 (1) load_const 2               (2) call_function            2 >>> Py_func (1, 2) [call_function]:na=2, Nk=0, n=2[call_function]:co->co_argcount=2, co->co_nlocals=2

  

2. Position parameter + key parameter

Py_func (1, b=2)//bytecode instruction 9 load_name                0 (py_func) load_const               1 (1) Load_const               2 (' B ') Load_const               3 ( 2) call_function            257>>> py_func (1, b=2) [Call_function]:na=1, Nk=1, N=3[call_function]:co->co_ argcount=2, co->co_nlocals=2

  

From the comparison of example 1 and Example 2, it can be seen that whether a parameter in a function parameter is a positional or a key parameter is actually determined only by the form of the function argument, but not with the formal parameters when the function is defined. From Example 1 to Example 2, the same is passed the parameter value 2 for the second parameter B, since the use of different forms of arguments, from the positional parameter to the key parameter. The (Na, NK) pairs also changed from (2, 0) to (1, 1). As can be seen, Na and NK do faithfully reflect the number of positional and key parameters.

Although in Example 1 and Example 2, the Na + NK value is the same, is 2, but we see that the value of n is different. In Example 1 o'clock N is 2, in Example 2 o'clock N is 3. This is derived from the formula for calculating n, n = Na + 2 * nk. Why is there such a formula? It's all about the meaning of N.

Ceval.c

Pyobject **pfunc = (*pp_stack)-n-1; Pyobject *func = *pfunc;

  

In Call_function, Func points to the Pyfunctionobject object that is stored in the runtime stack. And before this statement there is a sentence pyobject **pfunc = (*pp_stack)-n-1, where Pp_stack is the stack-top pointer of the current run-time stack. So, Pfunc is the result of the stack-top pointer fallback (N+1). From the instruction sequence of example 1 and Example 2, we can see that when the make_function instruction is executed, the Pyfunctionobject object is pressed into the runtime stack, and then all the information associated with the parameter is pressed into the runtime stack, and the number of information varies depending on the function. So, in call_function, we want to successfully fall back to the position of the Pyfunctionobject object, we must get the number of information about the parameter, this number is n. As we said before, NA is the number of positional parameters, and NK is the number of key parameters, because the key parameter will execute a load_const more than the positional parameter, and the symbol will be pressed into the runtime stack. Therefore, n = Na + 2 * NK

Why do key parameters cause two load_const instructions? In other words, is it necessary to pass B in Example 2? Consider a function with a default value, Def f (a=1, b=2, c=3), if we call F:f (b=1) so that we want to replace the default value of B, while preserving the default values of a and C, how do we not pass B,python how to know which variable to replace the default value? That's exactly what the key parameters do.

3. Position parameters + Extended position parameters

Def Py_func (A, B, *args):    Pass

  

Py_func (1, 2, 3, 4)//bytecode instruction 9 load_name                0 (py_func) load_const               1 (1) load_const 2               (2) Load_const               3 (3 ) Load_const               4 (4) call_function            4>>> py_func (1, 2, 3, 4) [Call_function]:na=4, Nk=0, N=4[call_ function]:co->co_argcount=2, co->co_nlocals=3

  

In the parameter table of the Python function, the position of the non-key parameter must precede the key parameter, so a function call such as Py_func (1, b=2, 3, 4) is illegal. As you can see from the NA value, the information for the extended position parameter is indeed attributed to the position parameter category

In the output information of the second row of [call_function], we found some special places, in Example 1 and Example 2, the value of Co_argcount and the value of Co_nlocals is the same, because there is no local variable inside the function. However, in example 3, the function also has no local variables, co_argcount and co_nlocals values are different, more strange, co_argcount as the number of function parameters, incredibly is 2, clearly py_func function declared a, B and *args 3 parameters. The only reasonable explanation is that Python internally expands the positional parameter *args as a local variable, so that there will be co_argcount=2 and co_nlocals=3 results

We can also see that, although we passed four arguments when we called the function, this did not affect the values of Co_argcount and co_nlocals. In fact, no matter how many arguments we pass, we cannot affect the values of O_argcount and co_nlocals. Because Co_argcount and co_nlocals are the fields of Pycodeobject objects that are generated after the function Py_func compiled, their values are determined at compile time. From the results of co_argcount=2,co_nlocals=3 we can already make a bold guess, that is, when Python implements the Py_func function, all the extended position parameters are actually stored in a Pylistobject object

4. Positional parameters + Extended key parameters

Def Py_func (A, B, **kwargs):    Pass

  

Py_func (1, 2, name= "Python", author= "Guido")//Byte code instruction 9 load_name                0 (py_func) load_const               1 (1) load_const               2 (2) Load_const               3 (' name ') load_const               4 (' Python ') load_const               5 (' author ') Load_const               6 ( ' Guido ') call_function           514>>> py_func (1, 2, name= "Python", author= "Guido") [Call_function]:na=2, nk=2, n=6[call_function]:co->co_argcount=2, co->co_nlocals=3

  

From the values of Co_argcount and co_nlocals, the extension key parameter is also seen as a local variable inside python.

5. Positional parameters + Local Variables

Def Py_func (A, B):    c = 1

  

Py_func (1, 2)//bytecode instruction 9 load_name                0 (py_func) load_const               1 (1) load_const 2               (2) call_function            2 >>> Py_func (1, 2) [call_function]:na=2, Nk=0, n=2[call_function]:co->co_argcount=2, co->co_nlocals=3

  

This co_nlocals=3 is taken for granted, because there is finally a local variable inside the Py_func function. From the command that executes the function call, there is no instruction that involves a local variable, which is undoubtedly correct, because the local variable belongs to another Pycodeobject

function mechanism of Python virtual machine (iii)

Related Article

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.