首页 > 编程语言 >python高级之函数的参数

python高级之函数的参数

时间:2023-12-10 19:44:47浏览次数:43  
标签:函数 python args sex 参数 print foo name

函数的参数

image

形参与实参介绍

函数的参数分为形式参数和实际参数,简称形参和实参:

形参即在定义函数时,括号内声明的参数。形参本质就是一个变量名,用来接收外部传来的值。

实参即在调用函数时,括号内传入的值,值可以是常量、变量、表达式或三者的组合:

#1:实参是常量
res=my_min(1,2)

#2:实参是变量
a=1
b=2
res=my_min(a,b)

#3:实参是表达式
res=my_min(10*2,10*my_min(3,4))

#4:实参可以是常量、变量、表达式的任意组合
a=2
my_min(1,a,10*my_min(3,4))

在调用有参函数时,实参(值)会赋值给形参(变量名)。在Python中,变量名与值只是单纯的绑定关系,而对于函数来说,这种绑定关系只在函数调用时生效,在调用结束后解除。

形参和实参的使用

位置参数

位置即顺序,位置参数指的是按顺序定义的参数,需要从两个角度去看:

​ 在定义函数时,按照从左到右的顺序依次定义形参,称为位置形参,凡是按照这种形式定义的形参都必须被传值

## 有位置而不传值会产生错误
def register(name,age,sex): #定义位置形参:name,age,sex,三者都必须被传值
    print('Name:%s Age:%s Sex:%s' %(name,age,sex))
    
register() #TypeError:缺少3个位置参数 
## TypeError: register() missing 3 required positional arguments: 'name', 'age', and 'sex'
'''
## 不按顺序传值会导致值的对应错误
def register(name, age, sex): # 定义位置形参:name,age,sex,三者都必须被传值
    print('Name:%s Age:%s Sex:%s' % (name, age, sex))

register(18, "男", "Xiao")
# Name:18 Age:男 Sex:Xiao
'''
## 正确的位置传参
def register(name, age, sex):  # 定义位置形参:name,age,sex,三者都必须被传值
    print('Name:%s Age:%s Sex:%s' % (name, age, sex))

register("Xiao", 18, "男")
# Name:Xiao Age:18 Sex:男

​ 在调用函数时,按照从左到右的顺序依次定义实参,称为位置实参,凡是按照这种形式定义的实参会按照从左到右的顺序与形参一一对应

关键字参数

​ 在调用函数时,实参可以是key=value的形式,称为关键字参数,凡是按照这种形式定义的实参,可以完全不按照从左到右的顺序定义,但仍能为指定的形参赋值

register(sex='male',name='lili',age=18)
Name:lili Age:18 Sex:male

位置和关键字混合使用

​ 需要注意在调用函数时,实参也可以是按位置或按关键字的混合使用,但必须保证关键字参数在位置参数后面,且不可以对一个形参重复赋值

register('lili',sex='male',age=18) #正确使用
register(name='lili',18,sex='male') #SyntaxError:关键字参数name=‘lili’在位置参数18之前
register('lili',sex='male',age=18,name='jack') #TypeError:形参name被重复赋值

默认参数

​ 在定义函数时,就已经为形参赋值,这类形参称之为默认参数,当函数有多个参数时,需要将值经常改变的参数定义成位置参数,而将值改变较少的参数定义成默认参数。例如编写一个注册学生信息的函数,如果大多数学生的性别都为男,那完全可以将形参sex定义成默认参数

  • 默认参数必须在位置参数之后
  • 默认参数的值仅在函数定义阶段被赋值一次
def register(name,age,sex='male'): #默认sex的值为male
     print('Name:%s Age:%s Sex:%s' %(name,age,sex))

默认参数的值通常应设为不可变类型

def foo(n,arg=[]):    
     arg.append(n)    
     return arg    
foo(1)    
[1] 
foo(2)    
[1, 2] 
foo(3)    
[1, 2, 3]

定义时就已经为参数sex赋值,意味着调用时可以不对sex赋值,这降低了函数调用的复杂度

register('tom',17) #大多数情况,无需为sex传值,默认为male
Name:tom Age:17 Sex:male
register('Lili',18,'female') #少数情况,可以为sex传值female
Name:Lili Age:18 Sex:female

小结:

为了防止有些参数重复或者报错 -- 默认参数
## 默认参数如果不想填,None
def index(name,age,gender='男'):
    print(f'{name}-{age}-{gender}')
## 默认参数不传参数的时候就使用默认值
index('dream',18)
## 默认参数传了参数就会覆盖掉默认值
index('hope',18,'女')

无论是默认参数的位置还是关键字参数的位置,一定要在位置参数后面

可变长参数

​ 参数的长度可变指的是在调用函数时,实参的个数可以不固定,而在调用函数时,实参的定义无非是按位置或者按关键字两种形式,这就要求形参提供两种解决方案来分别处理两种形式的可变长度的参数。

可变长位置参数(*args)

如果在最后一个形参名前加*号,那么在调用函数时,溢出的位置实参,都会被*接收,以元组的形式保存下来赋值给该形参

def foo(x,y,z=1,*args): #在最后一个形参名args前加*号
    print(x)
    print(y)
    print(z)
	print(args)
    
foo(1,2,3,4,5,6,7)  #实参1、2、3按位置为形参x、y、z赋值,多余的位置实参4、5、6、7都被*接收,以元组的形式保存下来,赋值给args,即args=(4, 5, 6,7)

1
2
3
(4, 5, 6, 7)

如果我们事先生成了一个列表,仍然是可以传值给*args的

def foo(x,y,*args):
    print(x)
    print(y)
    print(args)

L=[3,4,5]  
foo(1,2,*L) # *L就相当于位置参数3,4,5(解包), foo(1,2,*L)就等同于foo(1,2,3,4,5)
1
2
(3, 4, 5)

注意:如果在传入L时没有加*,那L就只是一个普通的位置参数了

def foo(x, y, *args):
    print(x)
    print(y)
    print(args)
L = [3, 4, 5]
foo(1, 2, L)
# 1
# 2
# ([3, 4, 5],)
# 如果在传入 L 时没有加 `*` ,那 L 就只是一个普通的位置参数了
# ([3, 4, 5],) ----> 为什么有一个 , ? 以元组的形式保存下来赋值给原来的参数

如果形参为常规的参数(位置或默认),实参仍可以是*的形式

def foo(x,y,z=3):
  	print(x)
    print(y)
    print(z)
 
foo(*[1,2]) #等同于foo(1,2)
1
2
3

如果我们想要求多个值的和,*args 就派上用场了

def index(*args):
    start = 0
    for i in range(len(args)):
        start += args[i]
    print(start)

## 1 + 2 + 3 
index(1, 2, 3)  # 6

可变长关键词参数(*kwargs)

  • 如果在最后一个形参名前加**号,那么在调用函数时,溢出的关键字参数,都会被 ** 接收,以字典的形式保存下来赋值给该形参
  • 可变长关键字参数 : 传实参的时候要按照关键字去传
def foo(x, **kwargs):  # 在最后一个参数kwargs前加**
    print(x)
    print(kwargs)


foo(y=2, x=1, z=3)
# 溢出的关键字实参y=2,z=3都被**接收,以字典的形式保存下来,赋值给kwargs
# 1
# {'y': 2, 'z': 3}
  • 如果我们事先生成了一个字典,仍然是可以传值给 **kwargs
def foo(x, y, **kwargs):
    print(x)
    print(y)
    print(kwargs)


dic = {'a': 1, 'b': 2}
foo(1, 2, **dic)
# **dic就相当于关键字参数a=1,b=2,foo(1,2,**dic)
# 等同foo(1,2,a=1,b=2)

# 1
# 2
# {'a': 1, 'b': 2}
  • 如果在传入 dic 时没有加 ** ,那 dic 就只是一个普通的位置参数了
def foo(x, y, **kwargs):
    print(x)
    print(y)
    print(kwargs)


dic = {'a': 1, 'b': 2}
foo(1, 2, dic)
'''
Traceback (most recent call last):
  File "E:\PythonProjects\01.py", line 358, in <module>
    foo(1, 2, dic)
TypeError: foo() takes 2 positional arguments but 3 were given
'''
  • 如果形参为常规参数(位置或默认),实参仍可以是 ** 的形式
def foo(x, y, z=3):
    print(x)
    print(y)
    print(z)


foo(**{'x': 1, 'y': 2})  # 等同于foo(y=2,x=1)

组合使用

def register(name, age, *args, **kwargs):
    user_dict = {'name': name, 'age': age}
    # 如果有位置参数进来而没有变量名接收的时候就会打包成元组,放到上面的字典中
    if args:
        user_dict['additional_info'] = args
    # 如果有关键字参数进来,就会被字典更新
    if kwargs:
        user_dict.update(kwargs)
    return user_dict


user_dict = register("Xiao", 18, "handsome",'music', hobby=["music"])
print(user_dict) # {'name': 'Xiao', 'age': 18, 'additional_info': ('handsome', 'music'), 'hobby': ['music']}

命名关键字参数

 在函数定义形参时,如果出现 * 隔断两边的形参,前面的参数任意(可位置/可关键字), * 后面的参数必须按照关键字传参数
def login(name,pwd,*,hobby,sex):
    print(f'{name}-{pwd}-{hobby}-{sex}')
login('dream', '521', hobby='music', sex='男')

# 命名关键字参数也可以使用默认值
# 默认关键字参数的位置可以放在位置参数前面
def login(name, pwd, *, hobby='music', sex):
    print(f'{name}-{pwd}-{hobby}-{sex}')


login('xiao', '000', sex='男')
login('xiao', '000', hobby='swim', sex='男')
- * 号后面的参数必须用关键字命名,* 前面任意使用
- 需要在定义形参时,用 * 作为一个分隔符号,* 号之后的形参称为命名关键字参数。
- 对于这类参数,在函数调用时,必须按照 key=value 的形式为其传值,且必须被传值

以上所有参数混合使用

  • 综上所述所有参数可任意组合使用,但定义顺序必须是:
    • 位置参数默认参数*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
  • 提示: *args**kwargs 中的 args 和 kwargs 被替换成其他名字并无语法错误,但使用args、kwargs是约定俗成的。

标签:函数,python,args,sex,参数,print,foo,name
From: https://www.cnblogs.com/xiao01/p/17893112.html

相关文章

  • allure commandline 命令行参数
    一、allurehtml产生流程方法一:alluregenerate+allureopen方法二:allureserver二、语法格式generateopenserver参考资料本文地址:https://www.cnblogs.com/hchengmx/p/17892977.html一、allurehtml产生流程Step1.test文件运行后产生allure-results文......
  • 生成函数
    使用场景:无穷级数与函数的对应。无穷级数:一个无限的数列的和。生成函数的应用:求组合求排列普通型生成函数:\(g(x)=\sum_{i=0}^\inftya_ix_i\)常见的普通型生成函数:\(\sum_{i=0}^\inftyx^i=\frac{1}{1-x}\)牛顿二项式定理:若\(0\le|a|<|b|\),且\(n\)是实数,则有\((1+......
  • Java开发者的Python快速实战指南:探索向量数据库之文本搜索
    前言如果说Python是跟随我的步伐学习的话,我觉得我在日常开发方面已经没有太大的问题了。然而,由于我没有Python开发经验,我思考着应该写些什么内容。我回想起学习Java时的学习路线,直接操作数据库是其中一项重要内容,无论使用哪种编程语言,与数据库的交互都是不可避免的。然而,直接操作M......
  • Python列表常见方法
    '''1.len()计算列表长度len(list)-->returnlen_number2.sorted()排序sorted()-->升序sorted(reverse=False)-->降序3.sum()计算列表所有元素的和值sum(list)-->returnsum_number4.max()查找最大值......
  • Spring Cloud Gateway实践(一):获取参数
    SCG(SpringCloudGateway)就我个人理解,是想让开发者把它作为一个较为简单的网关框架,只需简单在yml文件中写几个配置项就可以运行。所以它不大推荐在网关这一层获取body数据或者做一下复杂的业务处理。故而在实际编写代码中,获取queryParam很容易,但body数据就比较麻烦了,如果要修改就......
  • Python中级之异常处理
    异常处理引自:【6.0】Python中级之异常处理-Chimengmeng-博客园(cnblogs.com)【一】什么是异常异常是程序运行时可能发生的错误或意外情况。在Python中,异常是一种对象,表示程序执行期间发生的错误。当出现异常时,程序的正常流程会被中断,而是跳转到异常处理流程。【二】......
  • 如何更好的学习Python
    学习python需要有哪些思维任何编程语言时,培养一些特定的思维方式是非常有帮助的。下面是一些学习Python所需的思维方式:问题解决思维:学会将问题分解成更小、更可管理的部分,然后逐步解决每个部分。善于提问,学会将问题清晰地表达,有助于获取更好的帮助和解决方案。抽象思维......
  • 代码随想训练营第六十天(Python)| 84. 柱状图中最大的矩形
    84.柱状图中最大的矩形1、双指针classSolution:deflargestRectangleArea(self,heights:List[int])->int:n=len(heights)#左右第一个小于i的下标min_l,min_r=[0]*n,[0]*nres=0min_l[0]=-1......
  • #yyds干货盘点#深入了解Python类与面向对象编程
    类与对象的概念1.什么是类?类是一种用户自定义的数据类型,用于描述对象的属性和行为。它是对象的模板,定义了对象的结构。2.创建类使用class关键字来创建类。示范如何定义一个类,包括类名、属性和方法的定义。classDog:def__init__(self,name,breed):self.name=nam......
  • python算法
    目录: 回溯算法:  回溯算法:一般模型:results=[]defbacktrack(路径,选择列表):passif路径结束,满足约束条件:results.append(路径)#保存结果return#注意,返回到上一个分支,而不是返回结果,退出回溯if路径结束,不满足约束条件:......