在Python中,定义一个函数要使用def语句,python强制要求格式

1 定义

我们以自定义一个求绝对值的my_abs函数为例:

def my_abs(x):
    if x >= 0:
        return x
    else:
        return -x
调用my_abs(x)如下:
print(my_abs(-9))

1.1 空函数

def nop():
    pass

pass还可以用在其他语句里,比如:

if age >= 18:
    pass

缺少了pass,代码运行就会有语法错误。

1.2 返回多个值

函数可以返回多个值,比如在游戏中经常需要从一个点移动到另一个点,给出坐标、位移和角度,就可以计算出新的新的坐标:

import math

def move(x, y, step, angle=0):
    nx = x + step * math.cos(angle)
    ny = y - step * math.sin(angle)
    return nx, ny

然后,我们就可以同时获得返回值:

>>> x, y = move(100, 100, 60, math.pi / 6)
>>> print(x, y)
151.96152422706632 70.0

2 函数的参数

先看一个例子:power(x,n)求x的n次方

def power(x, n):
    s = 1
    while n > 0:
        n = n - 1
        s = s * x
    return s
>>> power(5, 2)
25
>>> power(5, 3)
125

2.1 必选参数,缺省参数

def power(x, n=2):#x是必选参数,n是缺省参数
    s = 1
    while n > 0:
        n = n - 1
        s = s * x
    return s

这样,当我们调用power(5)时,相当于调用power(5, 2).

注: 必选参数在前,默认参数在后
使用默认参数有什么好处?最大的好处是能降低调用函数的难度。

举个例子,我们写个一年级小学生注册的函数,需要传入name和gender两个参数:

def enroll(name, gender):
    print('name:', name)
    print('gender:', gender)

这样,调用enroll()函数只需要传入两个参数:

>>> enroll('Sarah', 'F')
name: Sarah
gender: F

如果要继续传入年龄、城市等信息怎么办?我们可以把年龄和城市设为默认参数:

def enroll(name, gender, age=6, city='Beijing'):
    print('name:', name)
    print('gender:', gender)
    print('age:', age)
    print('city:', city)

比如:

enroll('Bob', 'M', 7)
enroll('Adam', 'M', city='Tianjin')

2.2 可变参数

我们以数学题为例子,给定一组数字a,b,c……,请计算a2 + b2 + c2 + ……。

要定义出这个函数,我们必须确定输入的参数。由于参数个数不确定,我们首先想到可以把a,b,c……作为一个list或tuple传进来,这样,函数可以定义如下:

def calc(numbers):
    sum = 0
    for n in numbers:
        sum = sum + n * n
    return sum
>>> calc([1, 2, 3])
14
>>> calc((1, 3, 5, 7))
84

来看可变参数的写法:

def calc(*numbers): # 这里后面会讲numerbers是一个可迭代对象
    sum = 0
    for n in numbers:
        sum = sum + n * n
    return sum

定义可变参数时,仅仅在参数前面加了一个*号。在函数内部,参数numbers接收到的是一个tuple.但是,调用该函数时,可以传入任意个参数,包括0个参数:

>>> calc(1, 2)
5
>>> calc()
0

如果已经有一个list或者tuple,要调用一个可变参数怎么办?可以这样做:

>>> nums = [1, 2, 3]
>>> calc(nums[0], nums[1], nums[2])
14

这种写法当然是可行的,问题是太繁琐,我们在list或tuple前面加一个*号,

>>> nums = [1, 2, 3]
>>> calc(*nums) # 这里*nums相当于将列表nums打散
14

2.3 关键字参数

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

def person(**kw): # kw是keyword的缩写
    for k,v in kw.items(): 
        print(k,'=',v)
>>> person(name='job')
name = job
>>> person(name='job',age=30)
name = job
age = 30
>>> person(name='job',age=30,city='Beijing')
name = job
age = 30
city = Beijing

可见,**kw参数可以接受0到多个字典参数(key1=value1,key2=value2,…).

这样,直接这样写不可以:

>>> person({'name':'job','age':30)
TypeError: person() takes 0 positional arguments but 1 was given

可以这样:

>>>canshu1={'name':'job','age':30}
>>>person(**canshu1)

2.4 缺省参数,可变参数,关键字参数的综合应用
例1

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'}

例2

def f1(a, b, c=0, *args, **kw):
    print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)
    
>>>f1(1,2)
a=1 b=2 c=0 args=() kw={}
>>>f1(1,2,3)
a=1 b=2 c=3 args=() kw={}
>>>f1(1,2,3,'a','b')
a=1 b=2 c=3 args=('a','b') kw={}
>>>f1(1,2,3,'a','b',x=99)
a=1 b=2 c=3 args=('a','b'),kw={'x':99}

当然,通过一个元组(tuple)或字典(dict),可以调用f1.

>>>args=(1,2,3,4)
>>>kw={'d':99,'x':'beijing'}
>>>f1(*args,**kw)
a=1 b=2 c=3 args=(4,) kw={'d':99,'x':'beijing'}
>>>f1(7,8,*args,**kw)
a=7 b=8 c=1 args=(2,3,4) kw={'d':99,'x':'beijing'}

作业:
1 请定义一个函数quadratic(a, b, c),接收3个参数,返回一元二次方程:
$ax^2+bx+c=0$ 的两个解。

提示:计算平方根可以调用math.sqrt()函数

2 以下函数允许计算两个数的乘积,请稍加改造,变成可接收一个或多个数并计算乘积:

def product(x, y):
    return x * y