第六章 函数

一、函数概述  

(一)函数的定义

函数是组织好的、实现单一功能或相关联功能的代码段。以“函数名()”形式调用。

 1.未使用函数的程序

for i in range(5):
    for i in range(5):
        print('*',end=" ")
print()

2.使用函数的程序

def print_triangle(lenth):
    for i in range(lenth):
        for i in range(lenth):
            print('*'," ")
print()
print_triangle(5)

(二)函数式编程的优点:

  • 将程序模块化,既减少了冗余代码,又让程序结构更为清晰
  • 提高开发人员的编程效率
  • 方便后期的维护与扩展

二、函数的定义和调用

 (一)定义函数:def关键字

语法格式:

def 函数名 ([参数列表]):       #函数名是函数的唯一标识;参数列表可以  包含一个或多个参数

        函数体               #具体代码

        return                 #return函数的结束;若没有返回值,可以省略

计算两数之和的函数:

#无参函数
def add():
    result = 11 + 22
    print(result)


#有参函数

def add_modify(a, b):
    result = a + b
    print(result)

 (二)调用函数

1.函数要被程序调用时才会执行。

语法格式:

函数名([参数列表])

add()
add_modify(10, 20)

2. 函数内部可以调用其他函数(函数的嵌套调用)

def add_modify(a, b):
    result = a + b
    add()   	
    print(result)
add_modify(10, 20)

函数的嵌套(外层函数、内层函数)

def add_modify(a, b):
    result = a + b
    print(result)
    def test(): 
        print("我是内层函数")                  
add_modify(10, 20)

注意:

  • 函数外部无法直接调用内层函数
  • 只能通过外层函数间接调用内层函数

三、函数参数的传递

函数参数的定义:定义函数是设置的参数称为形式参数(形参),调用函数时传入的参数称为实际参数(实参)。

(一)位置参数的传递

调用函数时将实参按照相应的位置依次传递给形参

def get_max(a, b):
    if a > b:
        print(a,"是较大的值!")
    else:
        print(b,"是较大的值!")
get_max(8, 5)

(二)关键字参数的传递

1.通过“形参=实参”的歌声将实参与形参相关联,将实参按照相应的关键字传递给形参

def connect(ip, port):
    print(f"设备{ip}:{port}连接!")
connect(ip="127.0.0.1", port=8080)

2.使用符号“/”来限定部分形参只接收采用位置传递方式的实参

​
def func(a, b, /, c):
    print(a, b, c)

​
#错误的调用方式
#func(a=10,20,30)
#func(10,b=20,30)

#正确的调用方式
#func(10,20,c=30)

(三)默认参数的传递

定义函数时可以指定形参的默认值,在被调用时可以选择是否给带有默认值的形参传值

#定义:
def connect(ip, port=8080):
    print(f"设备{ip}:{port}连接!")

#调用:
connect(ip="127.0.0.1")
connect(ip="127.0.0.1", port=3306)

#结果:
设备127.0.0.1:8080连接!
设备127.0.0.1:3306连接!

 (四)参数的打包与解包

1.打包

(1)“*”——接收以元组形式打包的多个值

#定义:
def test(*args):
    print(args)

#调用:
test(11, 22, 33, 44, 55)

#结果:
(11, 22, 33, 44, 55)

(2)“**”——接收以字典形式打包的多个值 

#定义:
def test(**kwargs):
    print(kwargs)

#调用:
test(a=11, b=22, c=33, d=44, e=55)

#结果:
{'a': 11, 'b': 22, 'c': 33, 'd': 44, 'e': 55}

注意:

  • 函数中添加“*”或“**”的形参可以符合命名规范的任意名称,但是建议使用*args和**kwargs
  • 若函数没有接收到任何数据,参数*args*和*kwargs为空,即为空元组空字典

2.解包 

(1)实参是元组,可以使用“*”拆分成多个值,按位置参数传给形参

#定义:
def test(a, b, c, d, e):
    print(a, b, c, d, e)

#调用:
nums = (11, 22, 33, 44, 55)
test(*nums)

#结果:
11 22 33 44 55

(2)实参是字典,可以使用“**”拆分成多个键值对,按关键字参数传给形参

#定义:
def test(a, b, c, d, e):
    print(a, b, c, d, e)

#调用:
nums = {"a":11, "b":22, "c":33, "d":44, "e":55}
test(**nums)

#结果:
{'a': 11, 'b': 22, 'c': 33 , 'd': 44, 'e': 55}

(五)混合传递

参数传递的方式在定义函数或调用函数时可以混合使用

使用规则:

  1. 按位置参数传递的方式
  2. 按关键字参数传递的方式
  3. 按默认参数传递的方式
  4. 按打包传递的方式

在定义函数时的注意事项:

  • 带有默认值的参数必须位于普通参数之后
  • 带有“*”标识的参数必须位于带有默认值的参数之后
  • 带有“**”标识的参数必须位于带有“*”标识的参数之后 
#定义:
def test(a, b, c=33, *args, **kwargs):
print(a, b, c, args, kwargs)

#调用:
test(1, 2)
test(1, 2, 3)
test(1, 2, 3, 4)
test(1, 2, 3, 4, e=5)

#结果:
1 2 33 () {}
1 2 3 () {}
1 2 3 (4,) {}
1 2 3 (4,) {'e': 5}

 四、函数的返回值

(一)函数中的return语句会在函数结束时将数据返回给程序,同时让程序回到被调用的位置继续执行

#定义:
def filter_sensitive_words(words):
    if "山寨" in words:
        new_words = words.replace("山寨", "**")
        return new_words

#调用:
result = filter_sensitive_words("这个手机是山寨版吧!")
print(result)

#结果:
这个手机是**版吧!

(二)如果函数使用return语句返回多个值,那么这些值将会被保存到元组

#定义:
def move(x, y, step):
    nx = x + step
    ny = y - step
    return nx, ny     # 使用return语句返回多个值

#调用:
result = move(100, 100, 60)  	
print(result)

#结果:
(160, 40)

五、变量作用域

(一)局部变量和全局变量

1.局部变量

注意:

  • 函数内部定义的变量,只能在函数内部被使用
  • 函数执行结束之后局部变量会被释放,此时无法再进行访问
def test_one():
    number = 10    	              # 局部变量
    print(number) 	              # 函数内部访问局部变量
test_one()
print(number)     	              # 函数外部访问局部变量

 不同函数内部可以包含同名的局部变量

def test_one():
    number = 10      
    print(number)             # 访问test_one()函数的局部变量number
def test_two():
    number = 20
    print(number)             # 访问test_two()函数的局部变量number
test_one()
test_two()

#结果:
10
20

2.全局变量

全局变量可以在整个程序的范围内起作用,不受函数范围的影响

number = 10         			# 全局变量
def test_one():
    print(number)   			# 函数内部访问全局变量
test_one()
print(number)       			# 函数外部访问全局变量

#结果:
10
10

全局变量在函数内部只能被访问,而无法直接修改

# 定义全局变量
number = 10
def test_one():
    print(number) 
    number += 1
test_one()
print(number)

 

3.补充

LEGB

局部作用域(L)例如,局部变量和形参生效的区域
嵌套作用域(E)例如,嵌套定义的函数中外层函数声明的变量生效的区域
全局作用域(G)例如,全局变量生效的区域
内置作用域(B)例如,内置模块声明的变量生效的区域

按照L-E-G-B的顺序依次搜索,若四张区域中无法找到变量,程序抛出异常

(二) global和nonlocal关键字

1.global关键字

使用global关键字可以将局部变量声明为全局变量

number = 10                    # 定义全局变量
def test_one():
    global number              # 使用global声明变量number为全局变量
    number += 1
    print(number)
test_one()
print(number)

2.nonlocal关键字

使用nonlocal关键字可以在局部作用域中修改嵌套作用域中定义的变量

def test():
    number = 10
    def test_in():
        nonlocal number
        number = 20
    test_in()
    print(number)
test()

 六、特殊形式的函数

(一)递归函数

定义递归函数需要满足的条件:

  • 递归公式是求解原问题或相似的子问题的结构
  • 边界条件是最小化的子问题,也是递归终止的条件

递归函数的执行分为两个阶段:

  1. 递推:递归本次的执行都基于上一次的运算结果
  2.  回溯:遇到终止条件时,则沿着递推往回一级一级的把值返回来

定义递归函数的格式:

def 函数名([参数列表])

        if 边界条件:

                return 结果

        else:

                return 递归公式 

举例:

 

def func(num):
     if num == 1: 
         return 1
     else:
         return num * func(num - 1)
num = int(input("请输入一个整数:"))
result = func(num)
print("5!=%d"%result)

 (二)匿名函数

使用lambda关键字定义匿名函数,语法格式:

        lambda <形式参数列表>:<表达式>

匿名函数与普通函数的区别:

  • 普通函数在定义是有名称,而匿名函数没有名称
  • 普通函数的函数体包含多条语句,而匿名函数的函数体只能是一个表达式
  • 普通函数可以实现的功能比较复杂,匿名函数可以实现的功能比较简单
  • 普通函数能被其他程序使用,而匿名函数不能被其他程序使用
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值