定义函数
定义函数:返回两个数中的较大者
def my_max(a, b):
if a > b:
return a
return b
如果没有
return
语句,函数执行完毕后也会返回结果,只是结果为None
。return None
可以简写为return
空函数:如果一个函数什么都不做,
paas
语句不可缺少,否则会有语法错误
def nop():
pass
定义函数:接收3个参数,返回一元二次方程ax^2 + bx + c = 0的两个解,求根公式x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}
def quadratic(a, b, c):
mid = b * b - 4 * a * c
if mid < 0:
raise ValueError('参数错误: ', mid)
sqrt = math.sqrt(mid)
return (-b + sqrt) / (2 * a), (-b - sqrt) / (2 * a)
print(quadratic(2, 3, 1)) # (-0.5, -1.0)
print(quadratic(1, 1, 1)) # ValueError: ('参数错误: ', -3)
函数参数
位置参数
调用时按照参数位置,顺序传参的函数,如计算x的n次方函数
def power(x, n):
s = 1
while n > 0:
n = n - 1
s = s * x
return s
print(power(2, 3)) # 8
位置参数也可以使用关键字传参,使用关键字传参可以不按照定义顺序
res = power(x=2, n=3)
print(res) # 2
res2 = power(n=3, x=2)
print(res2) # 2
默认参数
计算x的n次方时,如果只传入x一个参数,默认计算x的平方,就可以使用默认参数
def power(x, n=2):
s = 1
while n > 0:
n = n - 1
s = s * x
return s
print(power(3)) # 9
print(power(x=3)) # 9
print(power(3, 2)) # 9
print(power(x=3, n=2)) # 9
print(power(n=2, x=3)) # 9
print(power(3, n=2)) # 9
# 关键字参数要在未知参数后面
print(power(x=3, 2)) # SyntaxError: positional argument follows keyword argument
使用关键字传参时可以不按顺序。
位置传参按位置顺序,关键字传参要放在最后(关键字传参不能放在位置传参前面,只要出现一个关键字传参,后面的参数就都要使用关键字传参)
def my_fun(a, b, c, d):
print(a, b, c, d)
my_fun(1, 2, c=3, d=4) # 1 2 3 4
my_fun(1, 2, c=3, 4) # SyntaxError: positional argument follows keyword argument
默认参数的坑:不要使用可变参数作为默认参数,以下参数函数给默认参数L后面追加元素,但每次调用该函数,默认参数都是同一个,因为L是可变参数,默认参数函数定义好后确定了值,所以L一直指向同一个对象
def add_end(L=[]):
L.append('END')
return L
# 使用默认参数调用
print(add_end()) # ['END']
print(add_end()) # ['END', 'END']
print(add_end()) # ['END', 'END', 'END']
# 正常调用没问题
print(add_end([1, 2])) # [1, 2, 'END']
稍加改造后调用正常,None
是不可变对象
def add_end(L=None):
if L is None:
L = []
L.append('END')
return L
# 使用默认参数调用
print(add_end()) # ['END']
print(add_end()) # ['END']
print(add_end()) # ['END']
可变参数
计算a2 + b2 + c2 +...函数可定义为可变参数
def calc(*numbers):
sum = 0
for n in numbers:
sum = sum + n * n
return sum
L = [1, 2, 3, 4]
print(calc(*L)) # 30
*L
表示把L
这个list变为可变参数传进去。
关键字参数
**kw
为关键字参数,可以传任意个带参数名的参数(关键字参数)
def person(name, age, **kw):
print('name:', name, 'age:', age, 'other:', kw)
# name: Jack age: 29 other: {'city': 'beijing', 'job': 'engineer'}
person('Jack', 29, city='beijing', job='engineer')
dd = {'city': 'beijing', 'job': 'engineer'}
person('Jack', 29, **dd)
*dd
表示把dd
这个dict的所有key-value用关键字参数传入到函数的**kw
参数。
命名关键字参数
关键字参数无法控制传入参数的数量,并且也不能控制传输关键字的名称,这可以使用命名关键字参数解决,需要一个
*
符号说明后面的参数是命名关键字参数
def person(name, age, *, city, job):
print(name, age, city, job)
person('Jack', 20, city='New York', job='Engineer') # Jack 20 New York Engineer
# TypeError: person() missing 1 required keyword-only argument: 'job'
person('Jack', 20, city='New York')
如果前面已经有了可变参数,那么后面的关键字参数定义时,前面不用加
*
def person2(name, age, *args, city, job):
print(name, age, args, city, job)
person2('Jack', 20, city='New York', job='Engineer') # Jack 20 () New York Engineer
person2('Jack', 20, 30, city='New York', job='Engineer') # Jack 20 (30,) New York Engineer
# TypeError: person() missing 1 required keyword-only argument: 'job'
person2('Jack', 20, city='New York')
命名关键字也可以有默认值
def person(name, age, *, city='Beijing', job):
print(name, age, city, job)
使用
*args
和**kw
是Python的习惯写法
参数组合
参数定义的顺序必须是:必选参数(位置参数)、默认参数、可变参数、命名关键字参数和关键字参数。
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)
对于任意函数,都可以通过类似func(*args, **kw)
的形式调用它,python解释器会按照参数顺序传参,直到遇到参数不匹配
args = (1,)
kw = {'d': 99, 'x': '#'}
f1(*args, **kw) # TypeError: f1() missing 1 required positional argument: 'b'
args = (1, 2, 3)
kw = {'d': 99, 'x': '#'}
f1(*args, **kw) # a = 1 b = 2 c = 3 args = () kw = {'d': 99, 'x': '#'}
args = (1, 2, 3, 4, 5)
kw = {'d': 99, 'x': '#'}
f1(*args, **kw) # a = 1 b = 2 c = 3 args = (4, 5) kw = {'d': 99, 'x': '#'}
可以传任意参数的函数定义
def any_arg(*args, **kw):
pass
相反,对于任意函数,都可以通过类似
func(*args, **kw)
的形式调用它,无论它的参数是如何定义的。例子:计算两个数的乘积,可接收一个或多个数并计算乘积
def mul(a, *numbers):
for n in numbers:
a = a * n
return a
print(mul(3)) # 3
print(mul(2, 3, 4)) # 24
评论区