二、函数的参数

函数的参数

  1. 函数声明时,括号里的参数我们称之为形参,即形式参数

  2. 形参的值是不确定的,只是用来占位,负责接收外部传来的值

    注意:

    1. 形参有多少个,在调用参数时就填入多少个实参,无论是多是少,都会报错
    2. 形参和实参是一一对应的关系,从左至右顺序对应
  3. 函数调用时传入的参数,才是真正参与运算的数据,我们称之为实参

在python中,函数的参数可以有很多种,且分别有不同的功能,我们为了防止功能间冲突,规定了参数的定义顺序必须为: 位置参数, 默认参数, *args, 命名关键字参数, **kwargs

参数的数据类型

在python中函数不会限制参数的数据类型,只会有一个建议性

# 规定参数的数据类型
def zhang(a:int,b:int):
	return a + b
print(zhang(1,2))	#3
print(zhang('he','i'))	#hei
# 对于这种方法,函数并不会报错,可以作为提示的效果

位置参数

def zzw(a,b,c):
    print(a,b,c)


zzw(1,2,3)    # 1 2 3

'''
函数的实参与形参是一一对应的,从左至右顺序对应

默认参数

有些函数的参数是,如果传递了参数,就使用传递的参数;如果没有传递参数,就使用默认参数

# 使用 = 号直接赋值,就可以作为该参数的默认参数
def zhang(a = 'zhang',b = 'san'):
    print(a,b)
zhang()    #zhang san
zhang('li','si')    #li si
'''
在形参时就使用 = 赋值的方式,就相当于直接赋值形参值
如果在后续调用函数时,放入的实参
那么就类似于变量的二次赋值,将原值给覆盖掉了
从而实现类似默认参数的作用
'''

可变参数

'''
语法:
	def 函数名(形参1,形参2,...,*ages)    
    函数体

*ages 代表可变参数

注意:
	1、对于匹配可变参数的实参使用元组进行存储
	2、可变参数名可以任意,但是*必须有,例如*a、*b...
'''
def zzw(a,b,*c):
    print(a,b,c,type(c))
zzw(1,2,3,4,5,6,7)
# 1 2 (3, 4, 5, 6, 7) <class 'tuple'>
# 对应的可变参数使用元组存储

关键字参数

在调用函数时,实参可以是key=value的形式,称为关键字参数,凡是按照这种形式定义的实参,可以完全不按照从左到右的顺序定义,但仍能为指定的形参赋值

需要注意在调用函数时,实参也可以是按位置或按关键字的混合使用,但必须保证关键字参数在位置参数后面,且不可以对一个形参重复赋值

def foo(name, age, sex):
    print(name, age, sex)
    
foo(sex='male',name='lili',age=18)
# lili 18 male

foo('lili',sex='male',age=18) # 正确使用

foo(name='lili',18,sex='male') 
# SyntaxError:关键字参数name=‘lili’在位置参数18之前

foo('lili',sex='male',age=18,name='jack') 
# TypeError:形参name被重复赋值

命名关键字参数

命名关键字参数限定函数的调用者必须以key=value的形式传值,Python3提供了专门的语法:需要在定义形参时,用*作为一个分隔符号,*号之后的形参称为命名关键字参数。对于这类参数,在函数调用时,必须按照key=value的形式为其传值,且必须被传值

def register(name,age,*,sex,height): #sex,height为命名关键字参数
	pass
 
register('lili',18,sex='male',height='1.8m') 
# 正确使用

register('lili',18,'male','1.8m') 
# TypeError:未使用关键字的形式为sex和height传值

register('lili',18,height='1.8m') 
# TypeError没有为命名关键字参数height传值。

可变长关键字参数

如果在最后一个形参名前加**号,那么在调用函数时,溢出的关键字参数,都会被**接收,以字典的形式保存下来赋值给该形参

'''
语法:
	def 函数名(形参1,形参2,...,**kwargs)    
    函数体

*ages 代表可变参数

注意:
	1、对于多出的关键字参数,kwargs使用字典存储
	2、可变长关键字参数名可以任意,但是**必须有,例如**a、**b...
'''

def foo(x,**kwargs): #在最后一个参数kwargs前加**
     print(x)        
     print(kwargs)   
 
foo(y=2,x=1,z=3) 
# 溢出的关键字实参y=2,z=3都被**接收,以字典的形式保存下来,赋值kwargs
# 1
# {'z': 3, 'y': 2}

参数的组合

综上所述所有参数可任意组合使用,但定义顺序必须是:位置参数、默认参数、*args、命名关键字参数、**kwargs

可变参数*args与关键字参数**kwargs通常是组合在一起使用的,如果一个函数的形参为*args与**kwargs,那么代表该函数可以接收任何形式、任意长度的参数

可变类型与不可变类型传参

#1. 不可变数据类型
def test(a):
    print(id(a))    #1621551024
    a = 100
    print(id(a))    #1621552608
x = 1
print(id(x))    #1621551024
test(x)
print(id(x))    #1621551024
print(x)    #1
'''
解析过程
第一步:text(x) ==> a = x 函数将变量x 所存储的地址信息赋值给了 变量a
第二步:a = 100 ,因为变量a 存储了变量x 的地址信息,此刻100赋值给a,值100 在内存中的地址就替换了变量x的地址信息
第三步:print(x) 因为从头到尾都是对变量a的操作,所以此时输出x时,值仍然还是1

可以通过id()内置函数来查看变量所存值的内存地址变化
1. x调用前后,其内存地址均没发生改变
2. 变量a在 a = x时,此刻内存地址为x的内存地址,当执行到 a = 100时,此刻内存地址就变成 值100 在系统内存中的地址了
'''

#2. 可变数据类型
def demo(nums):
    print(id(nums))    #26419432
    nums[0] = 10
    print(id(nums))    #26419432
y = [3,5,6,8,2]
print(id(y))    #26419432
demo(y)
print(id(y))    #26419432
print(y)    #[10,5,6,8,2]
'''
可见,对于可变数据类型,当可变数据类型作为函数的实参时,在函数内部对该数据进行修改时,函数外部的全局变量也会被修改,因为他们指向的都是同一个内存地址
'''
posted @ 2021-05-24 22:14  zzwYYYYYY  阅读(367)  评论(0)    收藏  举报