Python基础-day09
函数的参数问题:
def func(a, *args, b=1, **kwargs):
print(a)
print(args)
print(b)
print(kwargs)
func(1, 2, 3, c=10, d=11)
此时:
a=1
args=(2, 3)
b=1
kwargs={'c': 10, 'd': 11}
func(1, 2, 3, b=10, c=10, d=11)
此时:
a=1
args=(2, 3)
b=10
kwargs={'c': 10, 'd': 11}
动态参数的另一种传参方式:
def func(*args):
print(args)
# 调用方式如下
li = [1, 2, 3]
func(*li)
得到:
(1, 2, 3)
调用函数时,给一个序列加上*,就是将这个序列打散。
所以func(*li)等同于:
func(li[0], li[1], li[2])
也就是func(1, 2, 3)
此时,args接收到了这些位置参数,因此args=(1, 2, 3)
最终打印结果为(1, 2, 3)。
*的作用:
调用函数时,按序打散序列。
定义函数时,打包位置参数。
同理,**的作用:
调用函数时,打散字典。
定义函数时,打包所有关键字参数。
函数的注释:
def func(a, b):
"""
this func is used for what
:param a: what meaning of para a
:param b: what meaning of para b
:return: returned value of this func
"""
return a + b
默认参数的陷阱:
定义函数时,如果默认参数的值是一个可变数据类型,那么每次调用这个函数时,都会共享这个默认参数的值。
举例:
def func(li=[]):
li.append(1)
print(li)
func()
func()
func()
[1]
[1, 1]
[1, 1, 1]
改进方式:
def func(li=None):
if li is None:
li = []
li.append(1)
print(li)
func()
func()
func()
[1]
[1]
[1]
关于函数的参数为可变数据类型的解释:
函数是第一类对象,它跟整数、字符串一样是对象,可以赋值给变量,可以作为参数传递给其他函数,也可以作为函数返回值。
函数对象也有自己的属性。比如函数的名字、函数的默认值元祖。


def是一条可执行语句,python解释器在执行def语句时,会在内存中创建一个函数对象。
在全局命名空间中,有一个函数名会指向该函数对象。
记住,至始至终,不管函数调用多少次,函数对象只有 1个,不会因为调用多次,而出现多个函数对象。

函数对象生成之后,它的属性:名字和参数列表都将初始化完成。

初始化完成时,属性__defaults__中的第一个默认参数numbers指向一个空列表。
第一次调用时:

第二次调用时:

第三次调用时,第四次调用时,都是如此。
如果我们显式地指定numbers的值,结构图如下:
func(numbers=[10, 11])

执行完 func(numbers=[10, 11])后,在函数对象内部,numbers变量依然指向[1, 1,],并不会因为调用后就指向[10, 11]。
因为函数对象内部的numbers属于函数中的局部变量,而调用func时,传递的是全局变量,它俩不是一个变量。
换一种方式理解:
这个函数对象好比一个工厂。(创建函数对象时,它的默认材料会定好)
你调用工厂时,如果不传递材料,工厂会使用它自己的默认材料来生产产品。这会执行一次函数。
他调用工厂时,传递了特殊材料,于是工厂会采用他的特殊材料来生产产品。这会执行一次函数。
她调用工厂时,没有传递材料,工厂也还是会采用默认材料来生产产品。这同样会执行一次函数。
所以说,工厂始终只有一个,你调用一次,它就工作一次;你调用一百次,它就工作一百次。
你要是传递了材料,它就采用你的材料来工作;你要是没有传递材料,它就用它的默认材料。
这丝毫不影响工作。并不会因为说,他传递了特殊材料,就将工厂的默认材料给覆盖了,他传递的材料只是临时的。
这个解释太棒了,一下子解开了我的疑惑。
建议:不要用可变对象作为默认参数的值。
函数对象:(运行机制在哪里有参考文章呢)
def func():
print('hello world')
# 打印这个变量在内存中的身份地址
print(id(func))
# 打印这个变量的数据类型
print(type(func))
# 打印这个变量(函数对象的表现形式,一般是这个函数对象在内存的地址)
print(func)
# 调用这个函数
func()
定义func这个函数后,函数里面的打印语句并没有执行,而是等待被调用 ,然后才会执行输出语句。

浙公网安备 33010602011771号