python函数参数传递(params, *params, **params)

本文深入讲解Python中的函数参数类型,包括位置参数、默认参数、可变参数和关键字参数等,帮助读者理解如何灵活使用各种参数,提高编程效率。
该文章已生成可运行项目,

一般最开始接触也就是最简单的函数参数形如 def fuc(x) ,但是也有复杂的函数参数传递方式,总结一下python的传参方式,先介绍一下参数的基本类型,最后讲到最复杂的(**params)类型。

1. 位置参数

一个最简单的函数形式,其中x,y就是位置参数: 

def add_both(x, y):
    return x+y

2. 默认参数

  • 最大的好处是能降低调用函数的难度;
  • 必选参数在前,默认参数在后,否则Python的解释器会报错;
  • 当函数有多个参数时,把变化大的参数放前面,变化小的参数放后面。变化小的参数就可以作为默认参数。
def enroll(name, gender, age=6, city='Beijing'):
    print('name:', name)
    print('gender:', gender)
    print('age:', age)
    print('city:', city)

有多个默认参数时,调用的时候,既可以按顺序提供默认参数,比如调用enroll('Bob', 'M', 7),意思是,除了namegender这两个参数外,最后1个参数应用在参数age上,city参数由于没有提供,仍然使用默认值。

也可以不按顺序提供部分默认参数。当不按顺序提供部分默认参数时,需要把参数名写上。比如调用enroll('Adam', 'M', city='Tianjin'),意思是,city参数用传进去的值,其他默认参数继续使用默认值。

默认参数的坑

def add_end(L=[]):
    L.append('END')
    return L

连续调用默认参数调用add_end(),默认参数是[],但是函数似乎每次都“记住了”上次添加了'END'后的list,

原因解释如下:

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

>>> add_end()
['END']
>>> add_end()
['END', 'END']

定义默认参数要牢记一点:默认参数必须指向不变对象,这也是为什么大多数函数默认参数都是None;

def add_end(L=None):
    if L is None:
        L = []
    L.append('END')
    return L

为什么要设计strNone这样的不变对象呢?因为不变对象一旦创建,对象内部的数据就不能修改,这样就减少了由于修改数据导致的错误。此外,由于对象不变,多任务环境下同时读取对象不需要加锁,同时读一点问题都没有。我们在编写程序时,如果可以设计一个不变对象,那就尽量设计成不变对象。

3. 可变参数

可变参数就是传入的参数个数是可变的,可以是任意个。

类似最常见的情况就是传入的参数是list或者tuple,运用在循环里:

def cal_num(nums):
    for i in nums:
        print(i)
>>> cal_num([1, 2])
1
2

而定义可变参数就是在参数前加一个*号,改为可变参数;参数nums接收到的是一个tuple,函数代码完全不变。调用函数的时候传入任意个参数,包括0个;

def cal_num(*nums):
    for i in nums:
        print(i)
>>> cal_num(1, 2)
1
2

如果已经有一个list或者tuple,要调用一个可变参数怎么办?Python允许你在list或tuple前面加一个*号,把list或tuple的元素变成可变参数传进去*nums表示把nums这个list的所有元素作为可变参数传进去。这种写法相当有用,而且很常见。

>>> nums = [1, 2]
>>> cal_num(*nums)
1
2

4. 关键字参数

可变参数允许你传入0个或任意个参数,这些可变参数在函数调用时自动组装为一个tuple。而关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict。

函数person除了必选参数nameage外,还接受关键字参数kw。在调用该函数时,可以只传入必选参数,也可以传入任意个数的关键字参数:

def person(name, age, **kw):
    print('name:', name, 'age:', age, 'other:', kw)
>>> person('Michael', 30)
name: Michael age: 30 other: {}
>>> person('Bob', 35, city='Beijing')
name: Bob age: 35 other: {'city': 'Beijing'}
>>> person('Adam', 45, gender='M', job='Engineer')
name: Adam age: 45 other: {'gender': 'M', 'job': 'Engineer'}

4. 命名关键字参数

如果要限制关键字参数的名字,就可以用命名关键字参数,例如,只接收cityjob作为关键字参数。和关键字参数**kw不同,命名关键字参数需要一个特殊分隔符**后面的参数被视为命名关键字参数。

def person(name, age, *, city, job):
    print(name, age, city, job)
>>> person('Jack', 24, city='Beijing', job='Engineer')
Jack 24 Beijing Engineer

如果函数定义中已经有了一个可变参数,后面跟着的命名关键字参数就不再需要一个特殊分隔符*了。命名关键字参数必须传入参数名,这和位置参数不同。如果没有传入参数名,调用将报错。

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

 

 

 

 

参考链接:https://www.liaoxuefeng.com/wiki/1016959663602400/1017261630425888

 

本文章已经生成可运行项目
<think>好的,我现在要帮用户理解Python函数参数*号的作用。用户已经提到他们看过一些关于*args和**kwargs的解释,但可能还不太清楚具体的用法和区别。首先,我需要回忆一下自己学过的Python参数传递机制,确保信息准确。 用户给出的参考引用里提到,*args用来接收任意数量的位置参数,而**kwargs处理关键字参数。这可能已经覆盖了基本概念,但用户可能想知道更深入的用法,比如在函数定义和调用时的不同作用。比如,除了收集参数,*在函数调用时还可以解包可迭代对象,而**解包字典。这部分可能需要详细说明。 接下来,我需要分步骤解释。首先在函数定义中的用法,包括收集位置参数和关键字参数,以及强制关键字参数。这部分需要例子说明,比如使用*后面的参数必须用关键字传递。然后是在函数调用时的解包作用,比如将列表或元组解包成位置参数,字典解包成关键字参数。 还要注意用户可能的误区,比如***在定义和调用时的不同作用,容易混淆。需要明确区分这两种情况。另外,用户可能想知道实际应用场景,比如在处理可变参数或传递参数给其他函数时的便利性。 检查是否有遗漏的情况,比如单独使用*在参数列表中来分隔位置参数和关键字参数,这在Python3.8之后的版本中比较常见。这部分也需要提及,因为它可以帮助提高代码的可读性。 最后,生成相关问题,确保覆盖用户可能进一步想知道的内容,比如***的区别,实际应用例子,以及与类似语法的其他语言对比。同时,引用之前提供的资料,确保信息的一致性。 总结下来,回答的结构应该是先介绍*在定义中的三种用法,再介绍在调用时的解包作用,每个部分都配上示例代码,并最后给出相关问题帮助用户深入理解。</think>### Python函数参数*号的用法解释 在Python中,星号`*`在函数参数中有多种用途,主要分为**定义阶段****调用阶段**两种场景,其作用也截然不同。 --- #### 一、函数定义阶段 1. **收集位置参数** 单个`*`用于将多个位置参数打包为元组(即`*args`的经典用法)。 ```python def sum_numbers(*args): return sum(args) print(sum_numbers(1, 2, 3)) # 输出6 ``` 2. **分隔位置参数与关键字参数** 单独使用`*`可强制其后的参数必须通过关键字传递Python 3.8+特性)。 ```python def example(a, b, *, c): return a + b + c # example(1, 2, 3) # 报错,c必须用关键字传递 example(1, 2, c=3) # 正确,输出6 ``` 3. **收集关键字参数** 双星号`**`用于将关键字参数打包为字典(即`**kwargs`)。 ```python def print_info(**kwargs): for key, value in kwargs.items(): print(f"{key}: {value}") print_info(name="Alice", age=30) # 输出 name: Alice \n age:30 ``` --- #### 二、函数调用阶段 1. **解包可迭代对象为位置参数** 使用`*`可将列表/元组解包为独立的位置参数。 ```python def multiply(a, b): return a * b numbers = [3, 4] print(multiply(*numbers)) # 输出12 ``` 2. **解包字典为关键字参数** 使用`**`可将字典解包为关键字参数(键需与形参名匹配)。 ```python def greet(name, message): print(f"{message}, {name}!") params = {"name": "Bob", "message": "Hello"} greet(**params) # 输出 Hello, Bob! ``` --- #### 关键区别总结 | 场景 | 符号 | 作用 | 示例 | |-----------|------|---------------------------|------------------------| | 函数定义 | `*` | 收集位置参数或分隔参数类型 | `def func(a, *args):` | | 函数定义 | `**` | 收集关键字参数 | `def func(**kwargs):` | | 函数调用 | `*` | 解包可迭代对象为位置参数 | `func(*[1,2])` | | 函数调用 | `**` | 解包字典为关键字参数 | `func(**{'a':1})` | ---
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值