python:函数中五花八门的参数形式(茴香豆的『回』字有四种写法)
毫不夸张的说,python语言中关于函数参数的使用,是我见过最为灵活的,随便怎么玩都可以,本文以数学乘法为例,演示几种不同的传参形式:
一、默认参数
def multiply1(x, y):
return x * y print("multiply1:", multiply1(2, 3))
输出 multiply1: 6 ,这是最平淡无奇的函数写法。
python支持默认参数,比如:如果想让1个数自动乘10,又不想定义新的函数,上面的代码,可以改成:
def multiply1(x, y=10):
return x * y print("multiply1:", multiply1(2, 3))
print("multiply1:", multiply1(2))
输出
multiply1: 6
multiply1: 20
另外,调用函数时,除了按顺序依次给值外,还可以“显式”的命名传值,示例如下:
print("multiply1:", multiply1(x=2, y=4))
print("multiply1:", multiply1(y=3, x=5))
print("multiply1:", multiply1(x=4))
输出:
multiply1: 8
multiply1: 15
multiply1: 40
显式指定参数名称后,顺序就不重要了。
二、可变参数(tuple)
如果乘数多于2个,上面的版本显然不能满足要求,可以参考下面的版本:
def multiply2(*numbers):
result = 1
for i in numbers:
result *= i
return result print("multiply2(1):", multiply2(1, 2, 3))
test = (1, 2, 3)
print("multiply2(2):", multiply2(*test))
print("multiply2(3):", multiply2(test))
参数前加一个*,就表示参数个数不固定(其实python是当作tuple来看待),上面的代码会输出:
multiply2(1): 6
multiply2(2): 6
multiply2(3): (1, 2, 3) #注意这一行,如果是一个已经定义好的tuple变量,想传入可变参数中调用,必须前加*,否则的话,程序不报错,但不是你期望的结果。
当可变参数与默认参数结合在一起时,有一个地方需要注意:
def multiply2_2(*numbers, base=10):
result = 1
for i in numbers:
result *= i
return result * base print("multiply2_2:", multiply2_2(1, 2, 3, base=10))
输出:
multiply2_2: 60
这很好理解,但如果在前面再加一个默认参数:
def multiply2_3(x=2, *numbers, base=10):
print("x=", x, ",numbers:", numbers, ",base:", base)
result = 1
for i in numbers:
result *= i
return x * result * base print("multiply2_3(1):", multiply2_3(4, 1, 2, base=10))
print("multiply2_3(2):", multiply2_3(4, *(1, 2), base=10))
print("multiply2_3(3):", multiply2_3(*(1, 2), base=10))
# print("multiply2_3(4):", multiply2_3(x=4, *(1, 2), base=10)) # 这里会报错
输出:
x= 4 ,numbers: (1, 2) ,base: 10
multiply2_3(1): 80
x= 4 ,numbers: (1, 2) ,base: 10
multiply2_3(2): 80
x= 1 ,numbers: (2,) ,base: 10
multiply2_3(3): 20
注意:multiply2_3(*(1, 2), base=10) 这行调用时,(1,2)这个tuple里的第1个元素实际上是给到x了,从输出就能印证,函数定义中的x=2默认值,并没有起到作用。
如果把最后一行 print("multiply2_3(4):", multiply2_3(x=4, *(1, 2), base=10)) 的注释去掉,运行会报错:
print("multiply2_3(4):", multiply2_3(x=4, *(1, 2), base=10)) # 这里会报错
TypeError: multiply2_3() got multiple values for argument 'x'
原因在于(1,2)的第1个元素会赋值给x,然后又指定了x=4,所以python会认为参数x有2个值1、4,不知道该用哪个,只好蒙逼报错。
三、字典参数(dic)
如果在参数前加2个*,就变成字典(key-value)参数了,参考下面的示例:
def multiply3(**numbers):
result = 1
for a in numbers:
result *= numbers[a]
return result dic1 = {"a": 1, "b": 2, "c": 3}
print("multiply3(1):", multiply3(**dic1))
print("multiply3(2):", multiply3(**{"a": 1, "b": 2, "c": 3}))
print("multiply3(3):", multiply3(a=1, b=2, c=3))
注意调用的姿势,有好几种姿势可解锁~_^ 输出如下:
multiply3(1): 6
multiply3(2): 6
multiply3(3): 6
可能有同学感觉dic参数太灵活,单从调用参数的“长相”上,几乎就是一个json串,随便传,太浪了! 有没有什么办法约束一下,比如:要求dic字典中,只能包含指定的key。办法当然有:
def multiply4(*, a, b):
return a * b print("multiply4:", multiply4(**{"a": 2, "b": 3}))
print("multiply4:", multiply4(a=2, b=3))
print(multiply4(**{"a": 2, "b": 3, "c": 1}))
注意写法:*,a,b 表示该函数接受dic字典参数,但是dic中的key名称,只能是"a" , "b",输出:
multiply4: 6
multiply4: 6
Traceback (most recent call last):
File ".../03.py", line 42, in <module>
print(multiply4(**{"a": 2, "b": 3, "c": 1}))
TypeError: multiply4() got an unexpected keyword argument 'c'
即:最后一行调用print(multiply4(**{"a": 2, "b": 3, "c": 1}))时,这里出现了一个不守约定的key名:c ,所以报错了
当然,也可以配合默认参数,做些变化,比如:想给乘法结果设置一个基数。
def multiply5(base, *, a=1, b):
return base * a * b print("multiply5(1):", multiply5(10, **{"a": 2, "b": 3}))
print("multiply5(2):", multiply5(10, b=3))
输出:
multiply5(1): 60
multiply5(2): 30
四、大乱炖
如果把上面的各种奇淫技巧结合起来,就蛮头晕了,强烈不推荐!
def multiply6(a, b, c=1, *d, e=1, f):
print("a=", a, ",b=", b, ",c=", c, ",d=", d, ",e=", e, ",f=", f)
result = a * b * c
for i in d:
result *= i
result *= (e * f)
return result print("multiply6(1):", multiply6(1, 2, (3, 4, 5), f=6))
print("multiply6(2):", multiply6(1, 2, *(3, 4, 5), f=6))
print("multiply6(3):", multiply6(1, 2, 3, *(4, 5, 6), e=7, f=8))
输出:
a= 1 ,b= 2 ,c= (3, 4, 5) ,d= () ,e= 1 ,f= 6
multiply6(1): (3, 4, 5, 3, 4, 5, 3, 4, 5, 3, 4, 5, 3, 4, 5, 3, 4, 5, 3, 4, 5, 3, 4, 5, 3, 4, 5, 3, 4, 5, 3, 4, 5, 3, 4, 5)
a= 1 ,b= 2 ,c= 3 ,d= (4, 5) ,e= 1 ,f= 6
multiply6(2): 720
a= 1 ,b= 2 ,c= 3 ,d= (4, 5, 6) ,e= 7 ,f= 8
multiply6(3): 40320
tips: 首次调用故意少写了一个*,于是(3,4,5)这个元组就被乘了2*6次,变成了3,4,5连续重复12次。
def multiply7(a, b=10, *c, **d):
print("a=", a, ",b=", b, ",c=", c, ",d=", d)
result = a * b
for i in c:
result *= i
for j in d:
result *= d[j]
return result print("multiply7(1):", multiply7(2, *(3, 4), **{"x": 5, "y": 6}))
print("multiply7(2):", multiply7(2, *(3, 4), x=5, y=6))
print("multiply7(3):", multiply7(2, 3, 4, x=5, y=6))
print("multiply7(4):", multiply7(2, 3, 4, 5, 6))
输出:
a= 2 ,b= 3 ,c= (4,) ,d= {'x': 5, 'y': 6}
multiply7(1): 720
a= 2 ,b= 3 ,c= (4,) ,d= {'x': 5, 'y': 6}
multiply7(2): 720
a= 2 ,b= 3 ,c= (4,) ,d= {'x': 5, 'y': 6}
multiply7(3): 720
a= 2 ,b= 3 ,c= (4, 5, 6) ,d= {}
multiply7(4): 720
虽然看上去,调用方式各式各样,但是结果全是720,而且函数定义中的b=10,这个默认值完全不起作用。
五、多返回值
前面提到的都是入参的各种姿势,在函数返回结果上,python也有过人之处,可以一次返回多个元素:
def swap(x, y):
return y, x a, b = swap(1, 2)
print(a, b) result = swap(1, 2)
print(type(result), result)
输出:
2 1
<class 'tuple'> (2, 1)
tips: 多个返回值,只是假象,其实返回的是一个tuple对象。
参考文档:
python:函数中五花八门的参数形式(茴香豆的『回』字有四种写法)的更多相关文章
- Python函数中的可变参数
在Python函数中,还可以定义可变参数. 如:给定一组数字a,b,c……,请计算a2 + b2 + c2 + ……. 要定义出这个函数,我们必须确定输入的参数.由于参数个数不确定,我们首先想到可以把 ...
- Python函数中如何定义参数
一.位置参数:根据函数定义时的参数位置传递参数#形参和实参的个数必须一致def fun1(): print("运行结果") print("this is fun1(),n ...
- python函数中的关键字参数
关键字参数: 就是在形式参数中必须要提供”传递参数名=传递参数值” 位置参数: 仅仅只有参数名 特点:1.位置参数只能出现在关键字参数之前,不管是在行参还是实参中. 2.关键字参数在调用时(实参)中 ...
- Python——函数中的关键字参数
关键字参数 可变参数允许你传入0个或任意个参数,这些可变参数在函数调用时自动组装为一个tuple.而关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict.请看 ...
- matplotlib中 plt.plot() 函数中**kwargs的参数形式
plt.plot(x, y, **kwargs) **kwargs的参数大致有如下几种: color: 颜色 linestyle: 线条样式 marker: 标记风格 markerfacecolor: ...
- C#中克隆随机数的三种方法(为什么我想到了茴字的四种写法
C#中的Random类可以用来产生伪随机数(正确的废话 伪随机数的一个性质就是给定一个初始种子,那么产生的随机数列都是相同的,这个性质非常适合用在不同环境之间同步逻辑的场景. 最近有一个要克隆当前随机 ...
- python函数中把列表(list)当参数时的"入坑"与"出坑"
在Python函数中,传递的参数如果默认有一个为 列表(list),那么就要注意了,此处有坑!! 入坑 def f(x,li=[]): for i in range(x): li.append(i*i ...
- Python函数中参数类型
在学习Python函数的时候,函数本身的定义和调用并不是很复杂,但是函数的参数类型和用法的确有些复杂.在此做一个小结,加深理解. Python参数的定义 负责给函数提供一些必要的数据或信息,以保证函数 ...
- Python 函数中,参数是传值,还是传引用?
在 C/C++ 中,传值和传引用是函数参数传递的两种方式,在Python中参数是如何传递的?回答这个问题前,不如先来看两段代码. 代码段1: def foo(arg): arg = 2 print(a ...
随机推荐
- HTTP SIP 认证
HTTP请求报头: Authorization HTTP响应报头: WWW-Authenticate HTTP认证 基于 质询 /回应( challenge/response)的认证模式. ...
- 如何优雅打印nginx header和body
场景 参考https://segmentfault.com/a/1190000000606867可以获取response的报文体,由于业务测试有获取响应头Header或响应体Body的需求,这里是通过 ...
- 洛谷P3865 ST表
传送门啦 思路: $ f[i][j] $ 表示从 $ i $ 开始,包含 $ 1<<j $ 个元素的区间的区间最大值: 转移方程: $ f[i][j]=max_(f[i][j-1],f[i ...
- SpringBoot入门小案例
1.创建一个简单的maven project项目 2.下面来看一下项目结构: 3.pom.xml 配置jar包 <parent> <groupId>org.springfram ...
- python易错题之lambda 以及 for循环中内嵌函数
li = [] for x in range(10): print(x) //在函数没有执行前(li[0]()),for 循环中x已经执行完,x会一直为 9 def fun(): print(x) / ...
- hdu4638 莫队算法
莫队算法基础题,题目看懂就能做出来 #include<iostream> #include<cstring> #include<cstdio> #include&l ...
- python3的unittest中使用test suite(测试套件)执行指定测试用例
示例代码 module.py class baidumodule(): def __init__(self,driver,): self.dr = driver #不能在类中再次导入webdriver ...
- 「2017 山东一轮集训 Day7」逆序对
题解: 满满的套路题.. 首先显然从大到小枚举 然后每次生成的逆序对是1----(i-1)的 这样做dp是nk的 复杂度太高了 那我们转化一下问题 变成sigma(ai (ai<i) )= ...
- P2484 [SDOI2011]打地鼠
差分 代码: #include <bits/stdc++.h> using namespace std; #define INF 1999999999 ][],b[][],c[][]; i ...
- day15--JavaScript语言
JavaScript JavaScript是一门单独的编程语言.浏览器内置JavaScript的解释器. 独立的语言,浏览器具有js解释器. 存在与HTML中,在HTML中写JavaScript,存在 ...