5、函数的基础运用



1、内置函数

Python内部已经有了许多的内置函数,我们可以直接调用

示例1:

a = 3.65
b = int(a)  # int为内置函数
b

# 3

示例2:

c = -36.5
d = abs(c)  # abs内置函数,求绝对值
d

# 36.5
  • 调用函数的时候,如果传入的参数数量不对,会报TypeError的错误
abs(1, 2)  # abs()有且仅有1个参数

# 结果如下:
# TypeError: abs() takes exactly one argument (2 given)
  • 调用函数的时候,如果参数类型不对,也会报TypeError的错误
abs('a') # str是错误的参数类型

# 结果如下:
# TypeError: bad operand type for abs(): 'str'


2、自定义函数

语法:

def 函数名(参数列表):
    函数体

示例3:

  • 自定义一个绝对值函数
# 定义函数
def my_abs(x):
    if x<=0:
        return -x  # return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回 None
    else:
        return x

# 调用函数
my_abs(-12)

# 12

刚才定义的函数,如果出现参数数量不对,或者参数数据类型不对的情况下,会是什么结果

  • 参数的数量不对
my_abs(-12,10) # 可以看出,如果参数个数不对,Python解释器会自动检查出来,并抛出TypeError

           结果:
          

  • 参数的数据类型不对
my_abs('1213') # 可以看出,如果参数类型不对,Python解释器就无法帮我们检查

           结果:
          

由示例3可以看出,内置函数abs()会检查出参数错误,而定义的my_abs()没有参数检查,会导致if语句出错,出错信息和abs()不一样。所以,这个函数定义不够完善。
在下面的示例4中,我们修改一下my_abs()的定义,对参数类型做检查,只允许整数和浮点数类型的参数。数据类型检查可以用内置函数isinstance()实现:


示例4:

def my_abs(x):
    if isinstance(x,(int,float)): # 如果参数x是整形或浮点型数据,则往下执行
        if x<=0:
            return -x
        else:
            return x
    else:
        raise TypeError('bad operand type') # 提示错误信息
        
my_abs(-12)
# 12
  • 参数的数据类型不对
my_abs('a')

# 结果是:
# TypeError: bad operand type


3、返回多个值

函数可以返回多个值,但其多个值的返回,本质上是将多个值组成一个元组(tuple)


示例5:

  • 定义一个移动函数
def move(start_x, start_y, move_x, move_y):
    end_x = start_x+move_x
    end_y = start_y+move_y
    return end_x, end_y
  • 调用函数
r = move(1, 2, 5, 5)
print(r)  # 由下面的返回结果可以很直观的看出,函数多个值的返回,其实就是元组

# (6, 7)
  • 也可以这样调用
x, y = move(1, 2, 5, 5)  # 这种调用方式,就直接返回元组的每一个元素了
print(x, y)

# 6 7


4、参数

4.1、位置参数

位置参数,有时也称必备参数,指的是必须按照正确的顺序将实际参数传到函数中,否则结果会不一样

示例6:

  • 定义一个函数,用于求 a1 + a2 * a3 的值
def func_1(a1, a2, a3):
    r = a1 + a2 * a3
    return r

此时a1、a2、a3为位置参数,按照顺序传入函数

  • 假如:a1=1,a2=2,a3=3
result = func_1(1, 2, 3)
result
# 7
  • 再假如:a1=2,a2=1,a3=3
result = func_1(2, 1, 3)
result
# 5

由此可见,位置参数传输的顺序,直接影响到结果。

  • a1a2a3 是在定义函数阶段的参数,也称为形参
  • 123 是在执行函数阶段的参数,也称为实参

4.2、关键字参数

关键字参数是指使用参数的名字来确定输入的参数值(如:a1=1,a2=2,a3=3)。通过此方式指定函数实参时,不再需要与形参的位置完全一致,只要将参数名写正确即可(即:与顺序无关)

示例7:

以上面的func_1函数为例

result = func_1(a1=3, a2=5, a3=10) # a1=3, a2=5, a3=10 这种形式的参数,就是关键字参数
result
# 53

换个顺序,结果也是一样

result = func_1(a3=10, a1=3, a2=5)
result
# 53

4.3、默认参数

Python允许为参数设置默认值,即在定义函数时,直接给形式参数指定一个默认值。这样的话,即便调用函数时没有给拥有默认值的形参传递参数,该参数可以直接使用定义函数时设置的默认值。

Python定义带有默认值参数的函数,其语法格式如下:

def 函数名(形参名1, 形参名2, ..., 形参名 = 默认值):
    代码块

注意: 指定有默认值的形式参数必须在所有没默认值参数的最后,否则会产生语法错误。


示例8:

def func_2(a1,a2,a3=3):
    r = a1 + a2 * a3
    return r
  • 默认参数有指定的情况
result=func_2(1,2,5)
result
# 11
  • 默认参数没有指定的情况
result=func_2(1,2)
result
# 7

注意:默认参数必须指向不变对象!


示例9:

  • 定义add_end()函数,用于在列表最后添加一个END
def add_end(L=[]):
    L.append('END')
    return L
  • 第一次正常调用
add_end(['x', 'y', 'z'])
# ['x', 'y', 'z', 'END']
  • 第二次正常调用
add_end([1, 2, 3])
# [1, 2, 3, 'END']

到现在为止,没什么问题。但是如果调用的是空列表呢?

  • 第一次调用空列表
add_end()
# ['END']
  • 第二次调用空列表
add_end()
# ['END', 'END']
  • 第三次调用空列表
add_end()
# ['END', 'END', 'END']

原因:
因为函数在最初定义的时候,默认参数L的值就已经确定,而例子中的L是List类型,可变。所以每次调用该函数时,如果改变了L的内容,则下次调用时,默认参数的内容就会改变。

要修改上面的例子,我们可以用None这个不变对象来实现(即:将默认参数为可变类型,转化为不可变类型):

def add_end(L=None):
    if L is None:
        L = []
        L.append('END')
    return L

4.4、动态参数


示例10:

  • 我们来看下面这个例子:给定一组数字 a,b,c…… ,请计算 a^2 + b^2 + c^2 + ……

  • 定义函数

def func(numbers):
    sum=0
    for i in numbers:
        sum=sum+i*i
    return sum
  • 调用方式1—多个参数封装成列表
func([1,2,3])
# 14
  • 调用方式2—多个参数封装成元组
func((1,2,3))
# 14
  • 调用方式3—多个参数不封装
func(1,2,3)  # 结果错误

           结果:
          

由上面的例子,我们可以看出,如果将多个参数封装成一个列表或者元组,则能正常调用。但是如果不封装成1个,直接用多个参数,就会报错


4.4.1、位置参数的可变参数(*

示例11:

  • 将上面的示例,把函数的参数改为可变参数,如下:
def func(*args):  # *args是约定俗成的写法,也可以写成 *numbers
    sum=0
    for i in args:  # 上面是*args,这里就要改成args
        sum=sum+i*i
    return sum
  • 用不封装的多个参数
func(1,2,3)
# 14
  • 如果此时已经有了一个列表或者元组,应该如何变成可变参数呢?用*t1表示把t1这个元组的所有元素作为可变参数传进去
t1=(4,5,6)
func(*t1*)
# 77

*args 表示创建一个名为args的空元组,该元组可接受任意多个外界传入的非关键字实参


4.4.2、关键字参数的可变参数(**

  • 位置参数的可变参数,是*args;关键字参数的可变参数是 **kwargs

示例12:

def func(**kwargs):
    print(kwargs)
func(name='zhan',age=18,sex='man')
# {'name': 'zhan', 'age': 18, 'sex': 'man'}
func(name='zhan',age=18,sex='man',job='pythoner')
# {'name': 'zhan', 'age': 18, 'sex': 'man', 'job': 'pythoner'}

**kwargs 表示创建一个名为kwargs的空字典,该字典可以接收任意多个以关键字参数赋值的实际参数





posted @ 2022-03-23 11:48  taoshushu  阅读(97)  评论(0编辑  收藏  举报