Python-必选参数、默认参数、可变参数、关键字参数、命名关键字参数

本文详细介绍了Python函数参数的五种类型:必选参数、默认参数、可变参数、关键字参数和命名关键字参数。重点讲解了默认参数的陷阱以及如何避免,可变参数的使用方式,关键字参数如何自动组装为dict,以及命名关键字参数对参数名称的限制。最后提到了如何组合使用这些参数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.函数参数定义的顺序:必选参数(位置参数)、默认参数、可变参数、关键字参数、命名关键字参数

2.默认参数

(1)即,传的参数里面有默认值,可以通过传参替换;
(2)当有多个默认参数时,调用的时候,既可以按顺序提供,比如函数原定义enroll(name,sex,age=18,city="Beijing"),调用时可以enroll('Bob', 'M', 7),意思是,除了name,sex这两个参数外,最后1个参数应用在参数age上,city参数由于没有提供,仍然使用默认值;也可以不按顺序提供部分默认参数,但需要把参数名写上。如调用enroll('Adam', 'M', city='Tianjin'),意思是,city参数用传进去的值,其他默认参数继续使用默认值;

(3)但是会出现一个坑,如下:

def f(L=[]):
    L.append("aaa")
    return L


#正常调用,正常
print(f([1, 2, 3]))  # [1, 2, 3, 'aaa']

#开始使用默认参数,首次正常
print(f())  # ['aaa']

#再次调用,使用默认参数,就存在问题了
print(f())  # ['aaa', 'aaa']
print(f())  # ['aaa', 'aaa', 'aaa']

#原因解释如下:
#Python函数在定义的时候,默认参数L的值就被计算出来了,即[],因为默认参数L也是一个变量,它指向对象[],每次调用该函数,如果改变了L的内容,则下次调用时,默认参数的内容就变了,不再是函数定义时的[]了。

print(f([4, 5]))  # [4, 5, 'aaa']

上述现象可以如下更改:

def f(L=None):
    if L is None:
        L = []
    L.append("aaa")
    return L


print(f([1, 2, 3]))  # [1, 2, 3, 'aaa']
print(f())  # ['aaa']
print(f())  # ['aaa']
print(f())  # ['aaa']
print(f([4, 5]))  # [4, 5, 'aaa']

因此,定义默认参数必须指向不变对象

为啥呢?因为不变对象一旦创建,其内部的数据就不能修改,这样就减少了由于修改数据而导致的错误;此外,由于对象不变,多任务环境下同时读取对象不需要加锁,同时读就不会有问题;

3.可变参数

(1)即,就是传入的参数个数是可变的,可以是0个、1个、2个到任意个;

(2)以计算传入参数之和为例:

def calc(numbers):
    sum = 0
    for n in numbers:
        sum = sum + n * n
    return sum

#调用的时候,需以list或tuple形式传入
print(calc([1, 2, 3]))  #14
print(calc((1, 2, 3)))  #14

(3)再把传入的参数改为可变参数:

def calc(*numbers):
    sum = 0
    for n in numbers:
        sum = sum + n * n
    return sum

#在函数内部,参数numbers接收到的是一个tuple,但调用该函数时,可以传入任意个参数,包括0个参数
print(calc(1, 2, 3))  #14
print(calc())  #0

(4)基于以上,如果可变参数本身是一个list或tuple

def calc(*numbers):
    sum = 0
    for n in numbers:
        sum = sum + n * n
    return sum

#可以在list或tuple前面加一个*号,把list或tuple的元素变成可变参数传进去:
nums = [1, 2, 3]
print(calc(*nums))  # 14

注:*nums获得的是nums的一份拷贝,对*nums的改变不会影响nums的值
nums = [1, 2, 3]
print(calc(*nums, 4))  # 30
print("nums : ")
print(nums)

4.关键字参数

(1)允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict

def person(name, age, **kw):
    print("Name:", name, " Age:", age, "Other:", kw)

person("Mike", 22)  # Name: Mike  Age: 22 Other: {}
person("Mike", 22, sex="male")  # Name: Mike  Age: 22 Other: {'sex': 'male'}
person("Mike", 22, sex="male", city="Beijing")  # Name: Mike  Age: 22 Other: {'sex': 'male', 'city': 'Beijing'}

extra = {"sex": "male", "city": "Beijing",
         "job": {"job1": "Doctor", "job2": "Teacher"}}

person("Mike", 22, sex=extra["sex"], city=extra["city"], job=extra["job"])  #Name: Mike  Age: 22 Other: {'sex': 'male', 'city': 'Beijing', 'job': {'job1': 'Doctor', 'job2': 'Teacher'}}

person("Mike", 22, **extra, love="sing")  #Name: Mike  Age: 22 Other: {'sex': 'male', 'city': 'Beijing', 'job': {'job1': 'Doctor', 'job2': 'Teacher'}, 'love': 'sing'}

(2)**extra表示把extra这个dict的所有key-value用关键字参数传入到函数的**kw参数,kw将获得一个dict
(3)注:kw获得的dict是extra的一份拷贝,对kw的改动不会影响到函数外的extra,如下:

def person(name, age, **kw):
    kw["extrahaha"] = "lalala"
    print("Name:", name, " Age:", age, "Other:", kw)

person("Mike", 22, **extra, love="sing")  #Name: Mike  Age: 22 Other: {'sex': 'male', 'city': 'Beijing', 'job': {'job1': 'Doctor', 'job2': 'Teacher'}, 'love': 'sing', 'extrahaha': 'lalala'}
print("extra : ")
print(extra)  #{'sex': 'male', 'city': 'Beijing', 'job': {'job1': 'Doctor', 'job2': 'Teacher'}}


info = {"age": 18, "name": "Ann", "sex": "female", "city": "Shanghai"}

person(**info)  # Name: Ann  Age: 18 Other: {'sex': 'female', 'city': 'Shanghai', 'extrahaha': 'lalala'}

5.命名关键字参数

(1)如果要限制关键字参数的名字,就可以用命名关键字参数。命名关键字参数需要一个特殊分隔符 * ,*后面的参数被视为命名关键字参数

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

student("Anna", 15, city="Beijing", sex="female")  # Anna 15 Beijing female

info = {"age": 18, "name": "Ann", "sex": "female", "city": "Shanghai"}
student(**info)  # Ann 18 Shanghai female

(2)如果函数定义中已经有了一个可变参数,后面跟着的命名关键字参数就不再需要一个特殊分隔符*了

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

ex = [1, 2, 3]
student("Anna", 15, *ex, city="Suzhou", sex="male")  #Anna 15 (1, 2, 3) Suzhou male

(3)命名关键字参数可以有缺省值:

def student(name, age, *, city="Hangzhou", sex):
    print(name, age, city, sex)

student("Anna", 15, sex="male")  # Anna 15 Hangzhou male

(4)使用命名关键字参数时,要特别注意,如果没有可变参数,就必须加一个*作为特殊分隔符。如果缺少*,Python解释器将无法识别位置参数和命名关键字参数

def student(name, age, *, city="Hangzhou", sex):
    print(name, age, city, sex)

# student("Anna", 15, "Beijing", "female")  # 报错TypeError: student() takes 2 positional arguments but 4 were given

6.组合参数

def f1(a, b, c=0, *args, **kw):
    print("a=", a, "b=", b, "c=", c, "args=", args, "kw=", kw)


def f2(a, b, c=0, *, d, **kw):
    print("a=", a, "b=", b, "c=", c, "d=", d, "kw=", kw)


f1(1, 2)  # a= 1 b= 2 c= 0 args= () kw= {}
f1(1, 2, c=3)  # a= 1 b= 2 c= 3 args= () kw= {}
f1(1, 2, 3, "a", "b")  # a= 1 b= 2 c= 3 args= ('a', 'b') kw= {}
f1(1, 2, 3, "a", "b", x=99)  # a= 1 b= 2 c= 3 args= ('a', 'b') kw= {'x': 99}
f2(1, 2, d=99, ext=None)  # a= 1 b= 2 c= 0 d= 99 kw= {'ext': None}

args = (1, 2, 3, 4, 5, 6)
kw = {"d": 99, "x": "###"}
f1(*args, **kw)  # a= 1 b= 2 c= 3 args= (4,5,6) kw= {'d': 99, 'x': '###'}

args = (1, 2, 3,)
kw = {"d": 919, "x": "###"}
f2(*args, **kw)  # a= 1 b= 2 c= 3 d= 919 kw= {'x': '###'}

args = [1, 2, 3, 4]
kw = {"d": 99, "x": "###"}
f1(*args, **kw)  # a= 1 b= 2 c= 3 args= (4,) kw= {'d': 99, 'x': '###'}

args = [1, 2, 3]
kw = {"d": 919, "x": "###"}
f2(*args, **kw)  # a= 1 b= 2 c= 3 d= 919 kw= {'x': '###'}

在函数调用的时候,Python解释器自动按照参数位置和参数名把对应的参数传进去

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值