day10函数参数使用(2)

# -*- coding: utf-8 -*-
# @Time:
# @Auther: kongweixin
# @File:
"""
函数参数的使用
一,形参与实参介绍

二,形参与实参的具体使用
2.1位置参数
2.2关键字参数
2.3 默认参数
2.4可变长度的参数(*与**的用法)
2.4.1可变长度的位置参数
2.4.2可变长度的关键字参数
2.5命名关键字参数(了解)
2.6组合使用(了解)

"""
# 一,形参与实参介绍
# 含义:
"""
形参:在定义函数阶段定义的参数称之为形式参数,简称形参 相当于变量名
def func(x,y): #x=1 y=2
print(x,y)


实参:在调用函数阶段传入的值称之为实际参数,简称实参,相当于变量值
func(1,2)

print(x,y) #绑定关系只在函数体内进行

#形参与实参的关系:
#1.0 在调用阶段,实参(相当于变量值)会绑定(赋值=绑定内存地址)给形参(相当于变量名)
#2.0 这种绑定关系只能在函数体内使用
# 3.0 实参与形参的绑定关系在函数调用时生效,函数调用结束后解除绑定关系

实参是传入的值,但值可以是以下形式
形式一: 直接给值
func(1,2)
形式二:变量形式
a=1
b=2
func(a,b)

#形式三:func(int(2)
func(func1(1.2,),func2(2.3)333)
说白了只要是值就行 是什么无关 基本数据类型都可以!!!
"""

"""
二,形参与实参的具体使用
2.1位置参数:按照从左到右的顺序依次定义的参数称之为位置参数
1>位置形参:在函数定义阶段,按照从左到右的顺序直接定义的"变量名"
特点:特点:必须被传值,多一个不行少一个也不行
def func(x,y):
print(x,y)
func()
func(1,2)
func(1,2,3)
2>位置实参:在函数调用阶段,按照从左到有的顺序依次传值
特点: 按照顺序与形参-对应
func(1,2)
func(2,1)

2.2关键字参数
关键字实参:在函数调用阶段,按照key=value的形式传入的值
特点:指名道姓给某个形参传值,可以完全不参照顺序
def func(x,y)
print(x,y)

func(y=2,x=1)

#注意:混合使用,强调
# 1、位置实参必须放在关键字实参前
def func(x,y)
print(x,y)
func(1,y=2)
func(y=2,1)
# 2、不能为同一个形参重复传值
# func(1,y=2,x=3)
# func(1,2,x=3, y=4)

2.3 默认参数(默认形参参数)

#默认形参:在定义函数阶段,就已经被赋值的形参,称之为默认参数
特点:在定义阶段就已经被赋值,意味着在调用阶段可以不用为其赋值
def func(x,y=3): y=3就是默认的
print(x,y)
func(x=1)
#func(x=1) #输出结果:1 3
func(x=1, y=44444)#输出结果:1 44444 # 以你想传的为准

#那什么时候用位置形参 那什么时候用默认形参呢!!!

位置形参:是必须要传值的,所以当函数必须要有值的时候就用到位置形参!!

默认形参:在调用时候是要经常改变值,但不会改变函数本身,就可以进行设置为默认实参

# 举例:
# 比如机械班的同学进行信息输入(我们知道乃是众星捧月之式 女的很少)
def register(name,age,sex):
print(name,age sex)

register('三炮",18,'男")
register('二炮',19,'男)
register('大炮',19,'男)
register('没炮',19,'女')
# 这样定义是不是太复杂 因为女的就比较少输入会变得很复杂重复 ,那怎么办呢!!!

def register(name,age,gender="男"):
print(name,age,gender)

register('三炮',18)
register('二炮',19)
register('大炮',19)
register('没炮',19,gender="女")

#位置形参与默认形参混用,强调:
#1、位置形参必须在默认形参的左边
#def func(y=2,x):
# pass

# 2、默认参数的值是在函数定义阶段被赋值的, 准确地说被赋予的是值的内存地址.

def func(x,y=2):
print(x,y)
func(1)# 输出值默认是1 2
# 示例1
如果 这么写呢
m=2
def func(x,y=2): #y=-->2的内存地址
print(x,y)
m=333333
func(1)

输出结果呢!!! --->输出结果是 1 2 所以你可以知道 是在定义函数前进行赋值才可以

但是如果是这样的呢

m=[1111]
def func(x,y=m): #y=-->[1111]的内存地址
print(x,y)
m.append(2222)
func(1) #输出结果:1 [1111, 2222]

# 所以准确地说被赋予的是值的内存地址
# 虽然默认值可以被指定为任意数据类型,但是不推荐使用可变类型
m=[1111]
def func(x,y=m): #y=-->[1111]的内存地址
print(x,y)
m.append(2222)
func(1) #输出结果:1 [1111, 2222]



def func(x,y,z,l=None):
if l is None:
l=[]
l. append (x)
l. append(y)
l. append(z)
print(l)

func(1,2,3)

#所有在这里说一嘴 你在定义函数时 是最好是可以满足所有的变化在函数内进行 (就是不能受其他的影响)

2.4可变长度的参数(*与**的用法)
# 什么是可变长度:可变长度指的是在调用函数时,传入的值(实参)的个数不固定
#而实参是用来为形参赋值的,所以对应着,针对溢出的实参必须有对应的形参来接收


2.4.1可变长度的位置参数
#1:形参格式(*形参名):用来接收溢出的位置实参,溢出的位置实参会被*保存成元组的格式,然后赋值给形参

def func(x,y,*z):
print(x,y,z)
func(1,2,3,4,5,6)

def my_sum(*args): #通常为 *args(规定)
res=0
for item in x:
res+=item
return res
res=my_sum(1,2,3,4.5,6)
print(res)
#II:*可以用在实参中,实参中带* ,先*后的值打散成位置实参

# def func(x,y,z):
# print(x,y,z)
# # func(*[11,22,33])## func(11, 22..33)
# l=[11,22,33]
# func(*l)
# 或
# l=[11,22,33]
# func(*l)


#III:形参与实参中都带*
def func(x,y,*args):#args=(3,4,5,6)
print(x,y,args)
func(1,2,[3,4,5,6])
func(1,2,*[3,4,5,6])#func(1,2,3,4,5,6)


2.4.2可变长度的关键字参数
#1:形参格式(**形参名):用来接收溢出的关键字实参,溢出的位置实参会被*保存成字典的格式,然后赋值给形参
**后跟的可以是任意名字,但是约定俗成应该是kwargs


def func(x,y,** kwargs):
print(x,y,kwargs)
# func(1,y=2,a=1,b=2,c=3)
func(*[11,22,33]) #func(11,22,33)

#II:*可以用在实参中,实参中带** ,先**后的值打散成关键字实参

def func(x,y,z):
print(x,y,z)
# func(*{'x':1,'y':2,'z':3}) #func(x=1,y=2)
# func(** {'x':1,'y':2,'z':3})#func(x=1,a=2,z=3)
#错误

# func(*{'x':1,'y':2,})#func(x=1,y=2) #不能少
# TypeError: func() missing 1 required positional argument: 'z'
# TypeError:func()缺少1个必需的位置参数:“ z”
func(**{'x':1,'a':2,'z':3})#func(x=1,a=2,z=3) #不能多

# TypeError: func() got an unexpected keyword argument a
# TypeError:func()获得了意外的关键字参数a





#III:形参与实参中都带**

def func(x,y,**kwargs):
print(x,y,kwargs)
# func(y=222, x=111, a=333, b=444)
func(**{'y':222,'x':111,'a':333,'b':4444,})

#混用*与**时:#*args必须在**kwargs之前
# 示例 1
def func(*args,**kwargs):
print(args)
print(kwargs)
func(1,2,3,4,5,6,7,8,x=1,y=2,z=3)


# 示例2
def index(x,y,z,bbb):
print("index=>>>",x,y,z,bbb)
def wrapper(a,b,c,d):#a=1,b=2,c=3
index(a,b,c,d)#index(1,2,3)
wrapper(1,2,3,4)#wrapper的传递参数是给index用的# 也就是index()牵制wrapper()函数参数!!!

def index(x,y):
print(x,y)
def wrapper(*args, **kwargs):# args=(1,) kwargs={'y':2, 'z':3}
index(*args,**kwargs)
# index(*(1,),**{'y':2, 'z':3})
# index (1, z=3, y=2)
wrapper(y=2,z=3,x=1,)#不会被牵制但是要遵循index()的形参进行赋值实参






2.5命名关键字参数(了解)
在定义了**kwargs参数后,函数调用者就可以传入任意的关键字参数key=value,
如果函数体代码的执行需要依赖某个key,必须在函数内进行判断
def register(name,age,**kwargs):
if 'sex' in kwargs:
#有sex参数
pass
if 'height' in kwargs:
#有height参数
pass

想要限定函数的调用者必须以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 register(name,age,*,sex='male',height):
print('Name:%s,Age:%s,Sex:%s,Height:%s' %(name,age,sex,height))

register('lili',18,height='1.8m')
#输出结果:Name:lili,Age:18,Sex:male,Height:1.8m

需要强调的是:sex不是默认参数,height也不是位置参数,因为二者均在后,所以都是命名关键字参数,
形参sex=’male’属于命名关键字参数的默认值,因而即便是放到形参height之前也不会有问题。

另外,如果形参中已经有一个args了,命名关键字参数就不再需要一个单独的*作为分隔符号了
def register(name,age,*args,sex='male',height):
print('Name:%s,Age:%s,Args:%s,Sex:%s,Height:%s' %(name,age,args,sex,height))

register('lili',18,1,2,3,height='1.8m') #sex与height仍为命名关键字参数
#输出结果: Name:lili,Age:18,Args:(1, 2, 3),Sex:male,Height:1.8m

2.6 组合使用(了解)
综上所述所有参数可任意组合使用,但定义顺序必须是:位置参数、默认参数、args、命名关键字参数、*kwargs
可变参数*args与关键字参数kwargs通常是组合在一起使用的,如果一个函数的形参为*args与kwargs,
那么代表该函数可以接收任何形式、任意长度的参数
def wrapper(*args,**kwargs):
pass


在该函数内部还可以把接收到的参数传给另外一个函数(这在装饰器的实现中大有用处)
def func(x,y,z):
print(x,y,z)

def wrapper(*args,**kwargs):
func(*args,**kwargs)

wrapper(1,z=3,y=2)
#输出结果:1 2 3
按照上述写法,在为函数wrapper传参时,其实遵循的是函数func的参数规则,调用函数wrapper的过程分析如下:
1. 位置实参1被接收,以元组的形式保存下来,赋值给args,即args=(1,),关键字实参z=3,y=2被*接收,
以字典的形式保存下来,赋值给kwargs,即kwargs={'y': 2, 'z': 3}
2. 执行func(args,kwargs),即func((1,),* {'y': 2, 'z': 3}),等同于func(1,z=3,y=2)
提示: *args、**kwargs中的args和kwargs被替换成其他名字并无语法错误,但使用args、kwargs是约定俗成的。

"""

原文地址:https://www.cnblogs.com/kwkk978113/p/13252271.html