Thinking about Python parameters

Thinking about Python parameters

Xiaobian DevOps perspective

Introduction

    在群里和人讨论了有关python参数传递的机制。对方说是赋值传递,我持的观点是引用传递,讨论了许久,对方仍没讲解明白赋值传递的实现。我查看官方文档,官方文档的描述为:

Remember that arguments are passed by assignment in Python. The result of switching the official document to Chinese is: Remember that arguments are passed by assignment in Python. I didn't go into the official documents before. After today's discussion, I have made some thoughts on the passage of exploring the official documents in a simple way.
English version of the document link: https://docs.python.org/3/faq/programming.html#how-do-i-write-a-function-with-output-parameters-call-by-reference
Chinese version of the document link : Https://docs.python.org/zh-cn/3/faq/programming.html#how-do-i-write-a-function-with-output-parameters-call-by-reference

Pass by value and pass by reference


    值传递的方式,传入函数的参数是实际参数的复制品,不管在函数中对这个复制品如何操作,实际参数本身不会受到任何影响
     引用传递是指在调用函数时将实际参数的地址传递到函数中,那么在函数中所进行的修改,将影响实际参数。

Passing the parameters of the python function


    对于pythoner来说,在python中一切皆对象是众所周知的。对象又分为类似于数字不可变的对象和类似于字典可变的对象。
    先看下面的代码

def test(a , b) :
   a, b = b, a
  print("test函数里,a的值是", a, ";b的值是", b)
  print("test函数里,a的内存地址是", id(a), ";b的内存地址是", id(b))
a = 1
b = 2
test(a , b)
print("交换结束后,a的值是", a , ";变量b的值是", b)
print("交换结束后,a的内存地址是", id(a) , ";b的内存地址是", id(b))
       运行的结果如下

test函数里,a的值是 2 ;b的值是 1
test函数里,a的内存地址是 140705270535872 ;b的内存地址是 140705270535840
交换结束后,a的值是 1 ;变量b的值是 2
交换结束后,a的内存地址是 140705270535840 ;b的内存地址是 140705270535872
    从运行结果来看,在test函数里,a和b的值分别是2和1,交换结束后,变量a和b的值依然是1和2,并没有发生改变,程序中定义的变量a和b并不是test函数里的a和b。
    可以推测,test函数里的a和b只是主程序中变量a和b的复制品。
    代码开始只是定义了a和b两个变量,当程序运行到test函数时,进入 test函数,并将主程序中的a、b作为变量传入到test函数,此时,系统分别为主程序和test函数各分配一个栈区,用于保存各自的变量。
   将主程序中的a、b作为变量传入到test函数,实际上是在test函数栈区重新生成了两个变量a、b,并将主程序中a、b变量的值赋值给test函数栈区中的a和b,即对test函数中的a和b进行初始化。可以理解,是将a=1和b=2传递给了test函数,因此可以理解为将赋值传递给了test函数。只是在test栈区内,将test栈区内将test栈区a、b两变量所对应的内存地址交换了,但并未影响到主栈区内的a和b。

Thinking about Python parameters
Look at the following code


def test(d):
  d['a'], d['b'] = d['b'], d['a']
  print("test函数里,a元素的值是",d['a'], ";b元素的值是", d['b'])
  print("test函数里,a元素的内存地址是",id(['a']), ";b元素的值是", id(d['b']))

d = {'a': 1, 'b': 2}
test(d)
print("交换结束后,a元素的值是",d['a'], ";b元素的值是", d['b'])
print("交换结束后,a元素的内存地址是",id(['a']), ";b元素的值是", id(d['b']))
       运行结果如下

test函数里,a元素的值是 2 ;b元素的值是 1
test函数里,a元素的内存地址是 1612700978880 ;b元素的值是 140705270535840
交换结束后,a元素的值是 2 ;b元素的值是 1
交换结束后,a元素的内存地址是 1612700978880 ;b元素的值是 140705270535840

Is the result the same as the guess?
In fact, the same is true. The main stack area passes d = {'a': 1,'b': 2} to the test stack area, but the test stack area uses d['a'], d['b'] = d['b'], when d['a'] is exchanged, it uses operations on the dictionary itself {'a': 1,'b': 2}, not on the test stack area d Operations performed. The code is modified as follows


def test(d):
  d['a'], d['b'] = d['b'], d['a']
  print("test函数里,a元素的值是",d['a'], ";b元素的值是", d['b'])
  print("test函数里,a元素的内存地址是",id(['a']), ";b元素的值是", id(d['b']))
  d = None

d = {'a': 1, 'b': 2}
test(d)
print("交换结束后,a元素的值是",d['a'], ";b元素的值是", d['b'])
print("交换结束后,a元素的内存地址是",id(['a']), ";b元素的值是", id(d['b']))
      运行结果

```

In the test function, the value of the a element is 2; the value of the b element is 1 In the
test function, the memory address of the a element is 2532485631680; the value of the b element is 140705270535840 After the
exchange, the value of the a element is 2; the value of the b element 1
after the end of the exchange, a memory element address is 2532485631680; 140705270535840 element is the value of b

It is found that {'a': 1,'b': 2} itself has not been modified.
The next sentence from the official document is Since assignment just creates references to objects, there's no alias between an argument name in the caller and callee, and so no call-by-reference per se.

to sum up

1. It is not possible to divide the parameter transfer of python functions into variable objects and immutable objects to illustrate.
2. The transfer of python parameters is not passed by value or by reference, but is passed by assignment.
3. Directly use "=" to assign a value. No effect
4. If you want the function to modify the data, you can encapsulate the data into a variable object. The
above is the thinking about the python parameters. Please correct the deficiencies and unthinking points.

Thought questions

Finally, a piece of code is given:


def test(l):
   l[0] = "a"
   l = [4, 5, 6]

l = [1, 2, 3]
test(l)
print(l)

What is the result of the operation?
First of all, don't run it. First predict the result of the run, and post the predicted result in the message area, and then run it to see if it is the same as the predicted result.

Guess you like

Origin blog.51cto.com/15127511/2657825