Python参数深度解析:多样参数类型全掌握

4天前发布 gsjqwyl
6 0 0

文章标题:

Python参数全面剖析:各类参数类型深入了解

文章内容:

文章目录

  • 一、位置参数
  • 二、默认参数(Default Arguments)
  • 三、关键字参数
  • 四、可变位置参数
  • 五、可变关键字参数
  • 六、命名关键字参数/强制关键字参数
  • 七、组合使用

以下内容基于Python3.13展开讲解,对于Python3.x版本而言,下述内容均适用。

参数类型概览:
1、位置参数(Positional Arguments),属于必填参数
2、默认值参数(Default Arguments),为非强制传递参数
3、可变参数,非必传,不限制参数个数,例如给多个人发送邮件时,发送对象的数量不确定
4、关键字参数(Keyword Arguments),非必传,不限制参数个数,传入的关键字参数会被整合进一个字典中,传参时需采用k=v的形式
5、命名关键字参数/强制关键字参数(Keyword-Only Arguments)

在这里插入图片描述

一、位置参数

也被称作必传参数、顺序参数,是至关重要的,在调用函数时必须明确提供该类参数!位置参数需按照先后顺序一一对应传递,个数要准确无误。

定义:在给函数传递参数时,依照顺序依次传入值。

def add(a,b):
    print('a:{}, b:{}'.format(a,b))

print(add(1,2))

#运行结果:
D:\App\python\python3.13.0\python.exe D:\WorkSpace-Python\Test\test.py 
a:1, b:2

在此示例中,a和b即为位置参数,且这两个值必须传递,否则会报错。


二、默认参数(Default Arguments)

默认参数允许我们在函数定义时为参数设定默认值。若调用函数时未传递该参数,将使用预先设定的默认值。

def test(name,message='Boy'):
    print('name:{}, message:{}'.format(name,message))

test('Tom') #若不传递默认参数,则使用默认值
test('Alice','Girl')  # 输出:name:Alice, message:Girl
test('Alice',message = 'Girl') # 输出:name:Alice, message:Girl

#运行结果:
D:\App\python\python3.13.0\python.exe D:\WorkSpace-Python\Test\test.py 
name:Tom, message:Boy
name:Alice, message:Girl
name:Alice, message:Girl

默认参数使用注意要点
a. 默认参数必须置于位置参数之后,如此方能被解释器正确识别,不然会产生歧义。

def test(message='Boy',name): # SyntaxError: parameter without a default follows parameter with a default
    print('name:{}, message:{}'.format(name,message))
在这里插入图片描述

b. 默认参数务必指向不可变对象!

def defaultzero(arr = []):  #我们期望的是当arr参数为0时返回仅含一个0的arr
    arr.append(0)
    return arr
print(defaultzero())  #输出:[0]
print(defaultzero())  #输出:[0, 0] 显然重复调用时结果并非我们预期

#解决方案 使用None
def defaultzero1(arr = None):
    if arr == None:
        arr = []
        arr.append(0)
    return arr
print(defaultzero1()) #输出:[0]
print(defaultzero1()) #输出:[0] 重复调用时,输出结果一致

#这表明arr是一个对象
#实际上Python中所有数据类型均为对象

说明:上述结果可能与预期不同,缘由在于定义默认函数时,arr为可变变量,函数体载入内存时,默认参数arr所指向的空列表对象会被创建,且arr的内存地址保持不变,每次调用函数都会向arr变量中添加0

结果表明python解释器会将默认参数当作一个公共对象来处理,多次调用含默认参数的函数,会进行多次修改。

因此定义默认参数时一定要使用不可变对象(int、float、str、tuple)。使用可变对象语法上没错,但在逻辑上是不安全的,代码量非常大时,容易产生很难查找的bug。


三、关键字参数

关键字参数(Keyword Arguments)是在函数调用时通过参数名称来指定参数值的方式,无需按照定义形参的顺序传递参数。

def person(name, age):
    print('name:{}, age:{}'.format(name, age))

# 使用关键字参数调用函数
person(name='张三',age=20) #输出:name:张三, age:20
person(age=31,name='李四') #输出:name:李四, age:31

使用关键字参数调用函数时,对参数顺序没有要求。

若同时存在位置参数和关键字参数,位置参数必须置于关键字参数之前,否则会报错
在这里插入图片描述


四、可变位置参数

可变位置参数:Python函数提供了可变参数,以便在参数个数不确定时进行调用。可变参数会以tuple元组形式传递。

定义:可变参数意味着传入的参数个数可变,可为0个、1个、2个……多个。作用:能够一次向函数传递多个参数特征(格式):*args*参数(即在参数前加*号)】

def add(a,b):
    return a,b

#上述函数若传入多个参数需定义多个变量,可简化为可变参数形式
def add1(*args):
    print('args:{}, type:{}'.format(args,type(args)))
    result = 0
    for n in args:
        result = result + n
    return result

# 调用函数1
print(add1(1,2,3))

# 调用函数2
tupleArray=(1,2,3)
# *tupleArray这种方式较为常见且重要
print(add1(*tupleArray))  #输出结果:6

# 调用函数3
listArray=[1,2,3]
# *listArray这种方式较为常见且重要
# *listArray表示将listArray这个list中的所有元素作为可变参数传入
print(add1(*listArray))  #输出结果:6

#运行结果:
D:\App\python\python3.13.0\python.exe D:\WorkSpace-Python\Test\test.py 
args:(1, 2, 3), type:<class 'tuple'>
6
args:(1, 2, 3), type:<class 'tuple'>
6
args:(1, 2, 3), type:<class 'tuple'>
6

可以发现:*args的本质就是把入参以tuple形式传递
关于*星号的用法可参考另一篇博文:《python中的*用法详解


五、可变关键字参数

关键字参数非必传。Python的可变位置参数以tuple形式传递,而关键字参数则是以dict形式传递。即可变参数传递的是参数值,关键字参数传递的是参数名:参数值键值对。

定义:关键字参数允许传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict。在调用函数时,可仅传入必选参数:

def test(name,**kwargs):
    print("name:{}, kwargs:{}, kwargs-type:{}".format(name,kwargs,type(kwargs)))

#案例一:
test('张三') # 输出:name:张三, kwargs:{}, kwargs-type:<class 'dict'>

#案例二:
test('张三',age=10) # 输出:name:张三, kwargs:{'age': 10}, kwargs-type:<class 'dict'>

#案例三:
dictArray = {'city': 'Beijing', 'sex': '男'}
test('李四', **dictArray ) # 输出:name:李四, kwargs:{'city': 'Beijing', 'sex': '男'}, kwargs-type:<class 'dict'>

#**dictArray表示将dictArray这个dict的所有key-value以关键字参数形式传入函数的**kwargs参数,kwargs将获得一个dict。需注意kwargs获得的dict是dictArray的一份拷贝,对kwargs的改动不会影响函数外的dictArray。
#运行结果:
D:\App\python\python3.13.0\python.exe D:\WorkSpace-Python\Test\test.py 
name:张三, kwargs:{}, kwargs-type:<class 'dict'>
name:张三, kwargs:{'age': 10}, kwargs-type:<class 'dict'>
name:李四, kwargs:{'city': 'Beijing', 'sex': '男'}, kwargs-type:<class 'dict'>
  • **修饰的参数必须是最后一个
  • **修饰的参数必须以关键字的参数方式传参,Python解释器会将传入的关键字和关键字的值生成一个字典供函数内部使用

六、命名关键字参数/强制关键字参数

命名关键字参数 :强制关键字参数(Keyword-only arguments)是在3.1版本之后引入的,指在函数定义时,使用*后缀来限制函数调用时必须使用关键字参数进行传递,而不允许使用位置参数。

定义:例如仅接收city和sex的参数,其他参数不接收。

def person(*, city, sex):   # 使用分隔符“*”,表示后面的参数必须使用关键字传递
    print(city, sex)

person(city='USA',sex='男')  # 输出:USA 男

作用:限制要传入的参数的名字,只能传已命名关键字参数
特征:命名关键字参数需要一个特殊分隔符*,而后面的参数被视为命名关键字参数。

def person(name, age, *, city, sex):
    print(name, age, city, sex)

person('John',20,city='USA',sex='男')  # 输出:John 20 USA 男
#person('John',20,city='USA',birthday='1996-02-11') 报错 TypeError: person() got an unexpected keyword argument 'birthday'

关键字参数和命名关键字参数的区别
在于,前者可以传递任何名字的参数,而后者只能传递*后面名字的参数。如果函数定义中已经有了一个可变参数,后面跟着的命名关键字参数就不再需要一个特殊分隔符*了:

def person(name, age, *args, city, sex):
    print(name, age,args, city, sex)

person('John',20, *[1,2,3,4],city='USA',sex='男')

#运行结果:
D:\App\python\python3.13.0\python.exe D:\WorkSpace-Python\Test\test.py 
John 20 (1, 2, 3, 4) USA 男

七、组合使用

定义:将以上五种参数组合在一起的参数组合
排放顺序:在Python中定义函数,可使用必选参数、默认参数、可变参数、命名关键字参数和关键字参数,这5种参数均可组合使用。但需注意,参数定义的顺序必须是:必选参数–>默认参数–>可变参数–>命名关键字参数–>关键字参数。

可读性是代码的一个很重要的要求,所以尽量避免使用多种参数的组合。

def person(name, age,clas='二班', *args, **kwargs):
    print('name:{}, age:{}, clas:{}, args:{}, kwargs:{}'.format(name, age,clas,args, kwargs))

person('John',20) #输出:name:John, age:20, clas:二班, args:(), kwargs:{}
person('John',20,'4班',1,2) #输出:name:John, age:20, clas:4班, args:(1, 2), kwargs:{}
person('John',20,'4班',1,2,city='USA',sex='男') #输出:name:John, age:20, clas:4班, args:(1, 2), kwargs:{'city': 'USA', 'sex': '男'}
def f1(a, b, c=0, *, d, **kw):
    print('a:{},b:{},c:{},d:{},kw:{}'.format(a,b,c,d,kw))

f1(1,2,d=4)  # 输出:a:1,b:2,c:0,d:4,kw:{}
f1(1,2,3,d=4,e=5) #输出:a:1,b:2,c:3,d:4,kw:{'e': 5}

总结:

  1. 位置实参与关键字实参混合使用时,位置实参必须放在关键字实参前面(语法规定)
  2. 位置形参与默认形参混合使用时,位置形参必须在默认形参的左边
  3. *args**kwargs混合使用时,*args必须写在**kwargs的前面,否则会报语法错误

***的使用

  1. ***在函数定义处使用

  2. *:把多余的普通实参打包成元组

  3. **:把多余的关键字实参打包成字典

  4. ***在函数调用处使用

  5. *:对元组或列表进行解包

  6. **:对字典进行解包

  7. ***同时在函数定义处和调用处使用

  8. 先解包变成位置形参

  9. 再将多余的位置形参打包
# 示例一
def func(x, y, z):
    print(x, y, z)

func(*[1, 2, 3])
func(*(1, 2, 3))
func(**{"x": 1, "y": 2, "z": 3})

# 实例二
def func(x, y, z, *args):
    print(x, y, z)
    print(args)

func(5, 6, 7, *[1, 2, 3])
© 版权声明

相关文章

暂无评论

暂无评论...