Python高级之函数的参数

【一】形参和实参

  • 函数的参数分为形参和实参,形参就是定义在函数名后面括号里的参数(用来接收外部传来的值),实参就是调用函数时,括号里传进去的值(值可以是常量、变量、表达式)
def add(x, y):
    return x + y


#实参是常量
print(add(3, 4)) #输出 7
#实参是变量
x = 3
y = 4
print(add(x, y)) #输出 7
#实参是表达式
print(add(x * y, x + y)) #输出 19
#变量、常量、表达式的随机组合
print(add(x, 10 * (x+y))) #输出 73
#在调用有参函数时,实参(值)会赋值给形参(变量名)

【二】位置参数

  • 位置参数指按照顺序定义的参数
  • 在定义函数时,位置形参是按照从左到右的顺序依次定义形参,所以在调用函数时,位置实参也得按照从左到右的顺序依次定义实参
  • 只要是按照上面的形式定义的形参都必须被传值,并且实参要和形参的顺序保持一致

【1】有位置参数不传值会报错

#没有给位置参数传值给传值会报错
def login(name, password, tag):
    print(f"name:{name}|password:{password}|tag:{tag}")
    
    
login()
'''
Traceback (most recent call last):
  File "D:\Python\pythonProject\pythonProject1\demo7.py", line 82, in <module>
    login()
TypeError: login() missing 3 required positional arguments: 'name', 'password', and 'tag'
'''

【2】不按照位置传参数导致变量错误

#不按照位置传值,值与变量不对应,但不会报错
def login(name, password, tag):
    print(f"name:{name}|password:{password}|tag:{tag}")
    
    
login(123, True, 'ligo')
# name:123|password:True|tag:ligo

【3】对应位置形参

#要按照形参的位置传值
def login(name, password, tag):
    print(f"name:{name}|password:{password}|tag:{tag}")
    
    
login('ligo', 123, True)
# name:ligo|password:123|tag:True

【三】关键字参数

  • 关键字参数的实参是key = value的形式,而且可以不按顺序传参

【1】按顺序传参

#按照关键字传参数一定不能少参数,也不能多参数
def login(name, password, tag):
    print(f"name:{name}|password:{password}|tag:{tag}")
    
    
login(name='ligo', password=123, tag=True)
# name:ligo|password:123|tag:True

【2】不按顺序传参

#关键字传参不像位置传参,它可以不按顺序传参
def login(name, password, tag):
    print(f"name:{name}|password:{password}|tag:{tag}")
    
    
login(password=123, tag=True ,name='ligo')
# name:ligo|password:123|tag:True

【3】位置和关键字混合使用

#关键字传参也可以和位置传参一起用
#要注意的是,关键字参数必须在位置参数后面,并且不能对同一个形参赋值
def login(name, password, tag):
    print(f"name:{name}|password:{password}|tag:{tag}")
    
    
login( 'ligo',password=123, tag=True)
# name:ligo|password:123|tag:True

【四】默认参数

  • 在定义函数时,就已经为形参赋值,这类形参叫做默认参数
  • 默认参数一般设为不可变类型,并且设置参数时,位置参数一定在前,关键字参数在后

【1】默认参数不传值

#在形参中tag已经设置默认值为True了,所以在实参中可以不用传值
def login(name, password, tag=True):
    print(f"name:{name}|password:{password}|tag:{tag}")
    
    
login(name='ligo', password=123)
# name:ligo|password:123|tag:True

【2】默认参数传值

(1)默认参数初始化

#在实参中再次传值,会覆盖掉形参中的默认值
def login(name, password, tag=True):
    print(f"name:{name}|password:{password}|tag:{tag}")
    
    
login(name='ligo', password=123,tag=False)
# name:ligo|password:123|tag:False

(2)默认参数为可变数据类型

#可变类型的每一次调用会在上一次的基础上增加一个值到同一个列表中
def append_list(num,num_list=[]):
    num_list.append(num)
    return num_list
print(append_list(1)) # [1]
print(append_list(2)) # [1, 2]
print(append_list(3)) # [1, 2, 3]

(3)默认参数为空

#将参数中的列表拿到函数中,再去调用它,它每一次调用,都会覆盖上一个值
def append_list(num):
    num_list = []
    num_list.append(num)
    return num_list
print(append_list(1)) # [1]
print(append_list(2)) # [2]
print(append_list(3)) # [3]

【五】可变长参数

【1】可变长位置参数(*args)

(1)任意类型参数

  • 如果在最后一个形参名前加 * 号,那么在调用函数时,溢出的位置实参,都会被 * 接收,以元组的形式保存下来赋值给该形参
#【1】
def num(x, y, z, *args):
    print(x)
    print(y)
    print(z)
    print(args)


num(1, 2, 3, 4, 5, 6)
# 1
# 2
# 3
# (4, 5, 6)
#1,2,3被xyz取得,剩下的4、5、6被*接收到,以元祖的形式赋给args

#【2】如果形参为常规的参数(位置或默认),实参仍可以是*的形式
def num(x, y, z):
    print(x)
    print(y)
    print(z)


num(*[1, 2, 3])
# 1
# 2
# 3

#用*args求多个值的和
def num(*args):
    num = 0
    for i in args:
        num += i
    return num


print(num(1, 2, 3))  # 6

(2)解包

#如果我们事先生成了一个列表,仍然是可以传值给*args的
def num(x, y, *args):
    print(x)
    print(y)
    print(args)


num_list = [1, 2, 3]
num(1, 2, *num_list)
# 1
# 2
# (1, 2, 3)
#如果在传入列表时没有加*,那列表就只是一个普通的位置参数了

【2】可变长关键字参数(*kwargs)

  • 如果在最后一个形参名前加**号,那么在调用函数时,溢出的关键字参数,都会被 ** 接收,以字典的形式保存下来赋值给该形参
#【1】
def user(name, **kwargs):
     print(name)
     print(kwargs)


user(name='ligo', password=123, tag=True)
# ligo
# {'password': 123, 'tag': True}
#姓名后面的值会被**接受到,然后以字典的形式赋给kwargs

#【2】事先生成了一个字典,仍然是可以给**kwargs传值
def user(name, **kwargs):
     print(name)
     print(kwargs)

data_dict = {'password': 123, 'tag': True}
user(name='ligo', **data_dict)
# ligo
# {'password': 123, 'tag': True}
#如果在传入字典时没有加**,那字典就只是一个普通的位置参数了

#【3】如果形参为常规参数(位置或默认),实参仍可以是**的形式
def user(name, password, tag=True):
    print(name)
    print(password)
    print(tag)


user(**{'name': 'ligo', 'password': '123'})
# ligo
# 123
# True

【3】组合使用

def login(name, password, *args, **kwargs):
    print(f"name:{name}|password:{password}|{args}|{kwargs}")
    
    
login('ligo', 123, 1, 1, 11, 1, x=3)
# name:ligo|password:123|(1, 1, 11, 1)|{'x': 3}

【六】命名关键字参数

【1】函数内判断

  • 如果函数体代码的执行需要依赖某个key,必须在函数内进行判断
def login(name, password,**kwargs):
    if 'tag' in kwargs:
        pass

【2】命名关键字参数

  • 想要限定函数的调用者必须以key=value的形式传值
    • Python3提供了专门的语法:
      • 需要在定义形参时,用 * 作为一个分隔符号,* 号之后的形参称为命名关键字参数。
    • 对于这类参数,在函数调用时,必须按照key=value的形式为其传值,且必须被传值
def login(name, password, *, tag):
    print(f"name:{name}|password:{password}|tag:{tag}")
    
    
login(name='ligo', password=123, tag=True)
# name:ligo|password:123|tag:True


login('ligo', 123, 'True') #没有用关键字传参给tag传值会报错
'''
Traceback (most recent call last):
  File "D:\Python\pythonProject\pythonProject1\demo7.py", line 159, in <module>
    login('ligo', 123, 'True')
TypeError: login() takes 2 positional arguments but 3 were given
'''

【3】命名关键字参数默认值

#命名关键字参数也可以有默认值
def login(name, password, *, tag=True):
    print(f"name:{name}|password:{password}|tag:{tag}")
    
    
login(name='ligo', password=123)
# name:ligo|password:123|tag:True

#如果形参中已经有一个*args了,命名关键字参数就不再需要一个单独的 * 作为分隔符号了
def login(name, password, *args, tag=True):
    print(f"name:{name}|password:{password}|{args}|tag:{tag}")
    
    
login('ligo', 123, 1, 2, 3, 4, 5)
#name:ligo|password:123|(1, 2, 3, 4, 5)|tag:True

【七】混合使用

  • 综上所述所有参数可任意组合使用,但定义顺序必须是:位置参数、默认参数、*args 、**kwargs
  • 混合使用时不能使用关键字参数,并且*args 必须要在**kwargs的前面
def login(name, password, *args, **kwargs):
    print(f"name:{name}|password:{password}|{args}|{kwargs}")
    
    
login('ligo', 123, 1, 1, 11, 1, x=3)
# name:ligo|password:123|(1, 1, 11, 1)|{'x': 3}
  • 在该函数内部还可以把接收到的参数传给另外一个函数(这在装饰器的实现中大有用处)
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
posted @   Ligo6  阅读(196)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示