Python函数传递参数:对象引用

一、变量与对象

  1. Python 中一切皆为对象,数字是对象,列表是对象,函数也是对象,任何东西都是对象。

  2. 变量是对象的一个引用,又称名字或者标签,对象的操作都是通过引用来完成的。

  3. 赋值操作 = 就是把一个引用绑定到一个对象上。例如,[]是一个空列表对象,赋值给变量a,变量 a 是该对象的一个引用。

a = []
a.append(1)


二、对象的可变性

  1. 不可变对象:对象所指向的内存中的值不能被改变。不可变对象赋值给变量后,由于变量指向的值不可变,如果改变变量(准确的说是引用),相当于对变量进行了重新赋值,指向了内存中新的值。
  • 变量a引用了内存中的对象:1
a = 1
  • 对象1在内存中的地址
print(a, id(1))     
print(a, id(a))
1 4496995664
1 4496995664
  • 变量a重新赋值,引用了内存中的对象:2
a = 2
  • 对象2在内存中的地址
print(a, id(2))
print(a, id(a))
2 4496995696
2 4496995696


2. 可变对象:对象所指向的内存中的值可以被改变。如果改变变量(准确的说是引用),实际上只是对其所指的值进行了变更,并没有产生新的值,通俗点说就是原地改变。

lt = [1, 2, 3]
print(id(lt))
4551719624

lt.append(100)
print(id(lt))
4551719624
  1. Python中,数值类型(int和float)、字符串str、元组(tuple)都是不可变类型,而列表(list)、字典(dict)、集合(set)是可变类型。

三、函数传参

  1. Python函数中,参数传递的全部都是对象的引用,本质上是赋值操作,即把一个引用(变量)绑定到一个对象上。

  2. 参数是不可变对象时,不会对对象进行修改,相当于传递值。

  3. 参数是可变对象时,会对对象进行修改,相当传递引用。

  4. 在定义函数时,要注意函数的参数,传递的是值还是引用,特别是对于 默认参数 ,很容易导致潜在的bug。

四、函数的默认参数

  1. 默认参数是传递值时,仅仅在函数定义的时候赋值一次。
x = 8

def func(a, b=x):
    return a, b

print(func(1))
(1, 8)

x = 20
print(func(1))
(1, 8)
  • 示例中,默认参数b赋值为xx为不可变对象字符串8,当对x重新赋值为20后,调用函数时,默认参数b的值仍然为8
  • 默认参数的值,通常应该是不可变的对象,比如None、True、False、数字或字符串。
  1. 默认参数是传递引用时,通常为空,比如空列表[]或空集合{},但在定义函数时,尽量设置为None,而不要让参数直接等于空列表或空集合。
def fun(a, b = []):
    return b 

f = fun(1)
print(f)
[]

f.append(100)
print(f)
[100]
  • 像上述示例中,如果设置默认参数b = [],因为是可变对象,当默认参数b的对象,在其他地方被修改后,下次调用这个函数时其默认参数b 已不再是空列表。
  • 特殊情况下,比如在for循环中,调用默认参数为空列表[]或空集合{}的函数,可以循环累积迭代结果。

五、匿名函数捕获参数值

  1. lambda表达式中的参数x是一个自由变量, 是在执行时赋值(绑定),而不是定义时赋值(绑定),即lambda表达式中的参数x是执行时的值,这与函数的 默认参数 赋值不相同。
x = 10
a = lambda y: y + x

x = 20 
print(a(10))
30

 示例中,调用a(10)时,x取值为20,而不是定义时的10

  1. 如果想让匿名函数,在定义时就捕获到参数值,将参数x定义成默认参数即可,例如:
z = 10
a = lambda x, z=z: x + z 

print(a(2))
12

z = 7
print(a(2))
12

 示例中,对变量z重新赋值为7,再次调用函数a(2)时,匿名函数的参数z的值仍
 然为定义时的10,而不是7

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容