python参数的位置传递优点_关于Python中参数传递和作用域的问题?

想要了解 Python 的参数是如何传递的,首先要知道 python 的变量的内存管理机制。

不同的编程语言的内存分配策略有时是大相径庭,在 C 语言中分配内存时:

int a = 1;

现在想象下面这种情形:将 1 放入一个变量名为 a 的水杯中,这个水杯作为 1 的载体。上面这句语句就是创建出一块内存区域(a)来存储变量(水杯)的值(1)。

a = 2;

如果想要改变水杯中的值,只需要将想要修改的值(2)直接放入水杯中替换之前的1就完成了重新赋值。

int b = a;

将一个变量的值赋予其他的变量则会开辟新的存储空间,并复制当前水杯中的值,然后放入新的水杯。

---------------------------

而在 Python中变量的内存分配很诡异(至少对于我来说),变量不再是水杯了,而更像一个标签。在 Python中分配内存时:

a = 1

Python 这时将一个名为 a 的标签绑定到变量值 1 上。

a = 2

正如你所看到的,在修改变量值时,标签 a 是直接将自己绑定到内存中的值 2 上。

b = a

如果增加另一个变量 b 的值也为 2,标签 b 也会像 a 一样一起绑定到数值 2 上。

---------------------------

现在就可以讲讲参数传递的问题:

Python 中姑且可以说有两种函数变量传递的方式,一种称为 Call-by-value,另一种是 Call-by-reference(就是题主说的引用传递)。首先说说 call-by-value,在 call-by-value 中,参数表达式会被 Python 解释并绑定到函数中对应的变量中。所以如果参数表达式是一个变量,在函数中则会复制该变量的值然后再使用这个复制的值。因此这个变量值在函数外部作用域完全不会被改变。

在 call-by-reference 中:函数会直接使用一个值的隐含式的引用,而不是像 call-by-value 直接使用另外复制出的值,这样做的后果就是,在函数内部修改同名变量的值时导致外部的同名变量跟着改变。但这个传递方式也有很突出的优点:不论在时间还是内存空间效率都很高,因为不用另外复制变量。注意:严格意义上来说 Python 传参策略既不是 call-by-reference,也不是 call-by-value,而是另一种机制 call-by-object,亦 call-by-Object-reference ,或 call-by-sharing(参数传递是对一个对象的引用,但是这个引用却又是 passed by value)。根据不同的情况使用不同的机制,所以只是在这里用这两种方式来进行更确切地说明。

---------------------------

接下来看几个具体的示例:

下面是一个很让人费解的示例:

def a(the_list):

print('Got', the_list)

the_list.append('treats')

print('Set to', the_list)

outer_list = ['Dogs', 'eats']

print('Before, outer_list = ', outer_list)

a(outer_list)

print('After, outer_list = ', outer_list)

# Outputs in terminal

# >>> Before, outer_list = ['Dogs', 'eats']

# >>> Got ['Dogs', 'eats']

# >>> Set to ['Dogs', 'eats', 'treats']

# >>> After, outer_list = ['Dogs', 'eats', 'treats']

为什么会这样?因为 `the_list` 就是对 `list['Dogs', 'eats']` 的引用,而不是复制。并且在 Python 中 Object 对象是 mutable 可变对象(String等为不可变对象),所以 `append()` 方法能够改变 `the_list` 中的值。

理解上面的示例后,看下面更进阶的一个示例:

def b(the_list):

print('Got', the_list)

the_list = ['You', 'never', 'lie']

print('Set to', the_list)

outer_list = ['Dogs', 'eats']

print('Before, outer_list = ', outer_list)

a(outer_list)

print('After, outer_list = ', outer_list)

# Outputs in terminal

# >>> Before, outer_list = ['Dogs', 'eats']

# >>> Got ['Dogs', 'eats']

# >>> Set to ['You', 'never', 'lie']

# >>> After, outer_list = ['Dogs', 'eats']

为什么在这个例子中之前所说的不管用了呢?the_list 刚进入函数时,确实是对变量的引用,但是当 the_list = ['You', 'never', 'lie'] 这句语句执行之后,相当于直接在函数中又创建了一个新的局部变量,名字也叫 the_list, 本质上已经不同于参数the_list 。因为它将 the_list 绑定到了list['You', 'never', 'lie'] 上(想想之前所说的变量内存分配机制图,the_list 就像一个标签,直接绑定到了list['You', 'never', 'lie']上),所以自然也就没有改变 outer_list的值.

希望以上的回答能够解决题主对参数传递的疑惑。如有认知错误,欢迎指出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值