函数 (part 1)
本节主要将定义函数,以及函数的各种类型的参数细节
函数的主要作用就是打包代码以,最大程度的实现代码的重用,并将不同功能的代码进行封装,分解来降低结构的复杂度,提高可读性。
创建和调用函数
# 创建
def fun1():
pass # 空语句,常用作占位符。在规划程序的功能时候常用。
# 调用
fun1()
函数的返回值 return
语句
def div(x,y):
if y == 0:
return 'mistake'
else:
return x/y
div(4,2)
2.0
返回多个值
Python 将返回的多个值会以元组的形式打包。我们可以通过分别赋值来将返回值解包
def func1():
return 1,2,3
a = func1()
print(a,type(a))
(1, 2, 3) <class 'tuple'>
x,y,z = func1() # 将返回值解包
print(x,y,z)
1 2 3
注意:只要执行了 return
语句,函数就会立刻马上进行返回,不会再处理函数后面的语句。
所以上面的例子也可以像下面这么写:
def div(x,y):
if y == 0:
return 'mistake'
return x/y
a = div(4,0)
b = div(4,2)
print(a,b)
mistake 2.0
注意:如果一个函数我们没有通过 return
语句显示的返回内容, 函数也会在执行完函数体中所有语句后,返回一个 None
def func1():
a = 1+2
b = func1()
print(b)
None
函数的参数
形式参数 与 实际参数
形参(parameter)是形式参数的简称,又名Formal parameter,是在定义函数时跟在函数名后圆括号里面的变量名。
实参(argument)是实际参数的简称,又名Actual parameter,是在调用函数时跟在函数名后圆括号里面的值。
# 这个例子里 (x, times) 是形参;('function',3) 是实参
def fun1(x, times):
for i in range(3):
print(f'this is a {x}')
fun1('function',3)
this is a function
this is a function
this is a function
位置参数 与 关键字参数
位置参数
位置参数(positional argument),又称为定位参数,是在编程语言中函数或子程序调用的一种参数类型。 它们是根据参数在参数列表中的位置(而非名称)来确定其值的。
def func1(x,y,z):
return ''.join((x,y,z))
func1('a','b','c')
'abc'
func1('c','b','a') # 对于参数的调用者来说,要按照正确的顺序传递参数
'cba'
关键字参数
函数调用时,指定参数名称,称为关键字参数(keyword argument)(In computer programming, named parameters, named-parameter arguments, named arguments or keyword arguments refer to a computer language’s support for function calls to clearly associate each argument with a given parameter within the function call.)
func1(z='c',y='b',x='a') # 明确指定 'a' 是给到 x 这个参数
'abc'
注意:位置参数必须在关键字参数之前
func1('a','b',z='c')
# func1(x='c','b','a') 就会报错
'abc'
默认参数
默认参数指的是当函数调用中省略了实参时自动使用的一个值
def func1(x,y,z='ccccc'):
return ''.join((x,y,z))
print(func1('a','b')) # 不传递第三个参数,使用默认值
print(func1('a','b','c')) # 传递第三个参数,覆盖默认值
abccccc
abc
注意:使用默认参数的话,必须放置在最后
###### 以下代码会报错:SyntaxError: non-default argument follows default argument
# def func1(x='aaa',y,z='ccccc'):
# return ''.join((x,y,z))
def func1(y,x='aaa',z='ccccc'):
return ''.join((x,y,z))
func1('b') # 这样就没问题了
'aaabccccc'
用法:/
作用:/
左边的参数必须传递位置参数,而不能是关键字参数;而/
右侧随意,既可以使用位置参数也可以关键字参数
# 看一下几个 BIF 的文档
help(abs)
# abs(x=1.5) 报错:TypeError: abs() takes no keyword arguments
Help on built-in function abs in module builtins:
abs(x, /)
Return the absolute value of the argument.
help(sum)
Help on built-in function sum in module builtins:
sum(iterable, /, start=0)
Return the sum of a 'start' value (default: 0) plus an iterable of numbers
When the iterable is empty, return the start value.
This function is intended specifically for use with numeric values and may
reject non-numeric types.
# sum(iterable, /, start=0) 这里 左边的 iterable 必须是位置参数,而右边的 start 可以随意
print(sum([1,2,3],10))
print(sum([1,2,3],start=100))
16
106
# 我们也可以用 /
def func1(a,/,b,c):
print(a,b,c)
func1(1,2,3)
# func1(a=1,2,3) 会报错:SyntaxError: positional argument follows keyword argument
1 2 3
func1(1,b=2,c=3)
1 2 3
用法:*
作用:*
左边的参数既可以使用位置参数也可以关键字参数,而*
右侧必须传递关键字参数,而不能是位置参数
(个人看法:这个*
其实就是一个匿名的收集参数,后面不加参数名的话会被一起收进去)
def func1(a,*,b,c):
print(a,b,c)
func1(1,b=2,c=3)
# func1(1,2,3) 会报错:TypeError: func1() takes 1 positional argument but 3 were given
1 2 3
收集参数
收集参数,就是说只指定一个参数,然后允许调用函数时传入任意数量的参数
通过 *
打包到元组中 (*args
)
def func1(*ar):
print('In total, we have {} arguments.'.format(len(ar)))
print('the second argument is: {}.'.format(ar[1]))
print(ar) # here we can see ar is a tuple
print(type(ar))
func1(1,2,3,4,5)
In total, we have 5 arguments.
the second argument is: 2.
(1, 2, 3, 4, 5)
<class 'tuple'>
注意:如果在收集参数后面还要指定其他参数,那么在调用函数的时候,就必须要用关键字参数来指定后面的参数,否则python就会把实参纳入到收集参数中
def func1(*a,b,c):
print(a,b,c)
func1(1,2,3,4,5,b='A',c=3)
# func1(1,2,3,4,5) 就会报错:TypeError: func1() missing 2 required keyword-only arguments: 'b' and 'c'
## 否则 (1,2,3,4,5) 都收集到 *a 里了
(1, 2, 3, 4, 5) A 3
# 前文我们聊到 * 可以用作让 * 后面的参数必须是关键字参数, 如:
def func1(a,*,b,c):
print(a,b,c)
func1(1,b=2,c=3) # 这里就不能 func1(1,2,3)
print('-'*30)
# 其实这个星号就是一个匿名的收集参数,使得后面的必须使用关键字参数
def func1(a,*no_name,b,c):
print(a,b,c)
print(no_name)
func1(1,2,3,4,5,b='A',c='1')
1 2 3
------------------------------
1 A 1
(2, 3, 4, 5)
通过 **
打包到字典中 (**kwargs
)
此时我们传递参数必须要使用关键字参数,因为要打包给字典,=
左边传给键,=
右边传给值。
def func1(**kwa):
print(kwa)
func1(a=1,b=2,c=3)
{'a': 1, 'b': 2, 'c': 3}
混合使用:
def func1(a,*b,**c):
print(a)
print(b)
print(c)
func1(1,2,3,4,5,x=6,b=7,c=8)
1
(2, 3, 4, 5)
{'x': 6, 'b': 7, 'c': 8}
# 内置方法 混合使用的例子
help(str.format)
Help on method_descriptor:
format(...)
S.format(*args, **kwargs) -> str
Return a formatted version of S, using substitutions from args and kwargs.
The substitutions are identified by braces ('{' and '}').
解包参数
描述: *
和 **
不仅可以在函数定义的时候使用来打包,在函数调用的时候,可以用来解包。即在形参上使用用于参数的打包,在实参上使用用于参数的解包。
a = (1,2,3,4)
def func1(x,y,z,t):
print(x,y,z,t)
# 此时 func1(a) 会报错,因为需要四个参数却给了1个元组,一个参数
# 此时就要用 * 来解包
func1(*a)
1 2 3 4
a = {'x':1,'y':2,'z':3,'t':'A'}
# func1(*a) 此时这样传不可以,需要 ** 来解包成 关键字参数
func1(*a)
func1(**a)
x y z t
1 2 3 A
# 注意:
a = {'x':1,'y':2,'z':3,'t':'A','m':0,"n":9}
# func1(**a) 此时这样会报错:TypeError: func1() got an unexpected keyword argument 'm'
附言:
题目:Self-study Python Fish-C Note-11 P42-P44
本文为自学B站上鱼C的python课程随手做的笔记。一些概念和例子我个人为更好的理解做了些查询和补充
因本人水平有限,如有任何问题,欢迎大家批评指正!
原视频链接:https://www.bilibili.com/video/BV1c4411e77t?p=8