python栏 函数(递归/匿名/高阶/闭包/装饰器)

前言:想成为大佬,第一步,先学会写一份是人就能看懂的文档;今天开始,坚持写学习文档或分享;

一、什么是函数

佛祖保佑早点派个妹子收了我吧QAQ

print("                            _ooOoo_  ")
print("                           o8888888o  ")
print("                           88  .  88  ")
print("                           (| -_- |)  ")
print("                            O\\ = /O  ")
print("                        ____/`---'\\____  ")
print("                      .   ' \\| |// `.  ")
print("                       / \\||| : |||// \\  ")
print("                     / _||||| -:- |||||- \\  ")
print("                       | | \\\\\\ - /// | |  ")
print("                     | \\_| ''\\---/'' | |  ")
print("                      \\ .-\\__ `-` ___/-. /  ")
print("                   ___`. .' /--.--\\ `. . __  ")
print("                ."" '< `.___\\_<|>_/___.' >'"".  ")
print("               | | : `- \\`.;`\\ _ /`;.`/ - ` : | |  ")
print("                 \\ \\ `-. \\_ __\\ /__ _/ .-` / /  ")
print("         ======`-.____`-.___\\_____/___.-`____.-'======  ")
print("                            `=---='  ")
print("  ")
print("         .............................................  ")
print("                  佛祖镇楼                  BUG辟易  ")
print("          佛曰:  ")
print("                  写字楼里写字间,写字间里程序员;  ")
print("                  程序人员写程序,又拿程序换酒钱。  ")
print("                  酒醒只在网上坐,酒醉还来网下眠;  ")
print("                  酒醉酒醒日复日,网上网下年复年。  ")
print("                  但愿老死电脑间,不愿鞠躬老板前;  ")
print("                  奔驰宝马贵者趣,公交自行程序员。  ")
print("                  别人笑我忒疯癫,我笑自己命太贱;  ")
print("                  不见满街漂亮妹,哪个归得程序员?")

解释: 如果在开发程序时,需要某块代码多次执行。为了提高编写的效率以及更好的维护代码,需要把具有独立功能的代码块组织为一个小模块,这就是函数。

二、函数使用

1.函数定义/调用

def function(*args, **kwargs):
    pass

# 函数名()
function()

补充:函数调用时电脑内存操作

python栏 函数(递归/匿名/高阶/闭包/装饰器)_第1张图片
函数内存动态.png

2.函数参数

1.函数的参数会在两个地方使用到:

  • 函数的创建,小括号的内容叫做形参(表示将来将要传进来的数据)

  • 函数体的调用,小括号里的内容为实参(我现在就要传进去的数据)

2.函数文档注释/参数的种类/返回值

def fn(para1, para3=None, *args, **kwargs):
    """
    文档注释:解释函数的功能实现使用等信息
    :param para1:位置参数
    :param para3:缺省参数/关键字参数/默认参数
    :param args:不定长参数:接受位置参数
    :param kwargs:不定长参数:接受缺省参数
    :return:将函数中指定结果返回给函数调用者/结束函数标识/一个return 
    """
    return  a, b, c # (这样返回多个值,默认以元组返回)  # 返回值可以为空

# 拆包概念 - 直接把元组拆分为三个变量来使用,更加方便
a, b, c = fn(...)

3.全局变量和局部变量

局部变量:

  • 函数内部定义的变量

  • 其作用范围就只有在这个函数内部有效,函数执行完,函数对象的内存会被释放掉,函数的局部变量自然也会一起被释放掉

  • 局部变量存在的意义,在函数体中的逻辑设计中总会有一些数据需要一个容器来保存,但是它也许只会使用一次;如果我们在内存中给这个临时的变量单独开辟一个空间费事又费力,所以我们将其和函数绑定在一起;因为函数体在执行完以后会马上释放内存,这时我们将这些临时变量和函数一起释放就更加合理了;这样的临时变量我们就叫它局部变量,因为它是只在函数内部一小块地方使用。

全局变量:

  • 有局部变量自然有全局变量啦

  • 与局部变量的定义差不多,只是全局变量的作用范围是整个程序,程序存在,那么全局变量就存在。

  • 和局部变量相似,全局变量是存在内存空间为程序开辟的空间里,所以程序还在,全局变量就还在。

4.修改全局变量 global

  • 同名问题:如果函数外有全局变量 par ,现在我在函数内写一个par变量,是全局还是局部?;答案是局部变量。(如果其实想用的就是全局变量par,要在局部变量前加global)

5.查看全局变量和局部变量

python提供了两个内置函数globals()locals()可以用来查看所有的全局变量和局部变量

a = 100
def function():
    a = 10
    print('函数内locals():', locals())
    print('函数内globals()', globals())
    return 

function()

# 注意:在函数体外,局部也就是全局,所以下面两个输出一致
print('函数外locals():', locals())
print('函数外globals()', globals())

图解:

python栏 函数(递归/匿名/高阶/闭包/装饰器)_第2张图片
局部变量和全局变量.png

递归函数

简单说:函数自己调用自己视为递归

# 递归框架
def recursion():
    return recursion()

"""
思路:有规律的算法,从结局往开始走,于开始设立出口
场景:兔子问题(1,1,2,3,5...)
def f(n):
    if n == 1 or n == 2:
        return 1
    return f(n - 1) + f(n -2)
"""

匿名函数-lambda

语法:lambda 参数列表:语句

表达式里允许执行一条语句(调用函数,print(),运算表达式),可以看作for的简化版,书写简单

应用场景:以函数作为参数传递

# 以字典中成绩来排序
x = {'name': 'zhangsan','score': 100,...}
x.sort(key=lambda y: y['score'], reverse=False)

高阶函数

在python中,函数其实也是一种数据类型(function),是数据类型我们就可以把它当作数字或者字符串来处理。

1.把一个函数当作另一个函数的返回值

2.把一个函数当作另一个函数的参数

3.函数内部再定义一个函数

# 创建f3函数对象
f3 = lambda :print('f3被调用')

# 创建f1函数对象
def f1(f3):
    print('f1被调用')
    # f1内创建f2函数对象
    def f2():
        print('f2被调用')
    f2()
    return f3()

# 将f3当作参数传入f1中
f1(f3)

闭包

在函数的内部函数里,对外部函数作用域的变量进行引用,那么函数内部函数就被认为是闭包

处理闭包问题;一般可以用nonlocal

# 闭包现象

def fn1():
    a = 10
    def fn2():
        a += 10

# 当fn2想要修改fn1函数中的a值时,就会出现闭包现象
# 解决办法 在fn2函数的a值前加 nonlocal 这时程序就会知道,fn2中的a是fn1的变量

图解:

python栏 函数(递归/匿名/高阶/闭包/装饰器)_第3张图片
闭包现象.png

装饰器

执行步骤:

第一步:执行装饰器函数

第二步:传递被装饰的函数给装饰器fn参数

第三步:被装饰器函数调用时,调用的是装饰器的内部函数inner(),返回值是inner的返回值

# 装饰器框架
def decorator(fn):
    
    def inner(arguments2):
        fn(arguments1)
        return None
    return inner

# 装饰器调用
@decorator
def pafn(arguments1):
    pass

# 执行函数体
pafn(arguments2)

result = check_time(go_to_bed)
result() 

# 等同于把go_to_bed 当做参数传入给 check_time函数,再定义一个变量用来保存check_time的运行结果
# check_time 函数的返回值result是一个函数, result()再调用这个函数,让它再调用go_to_bed函数

# 装饰器带参数框架
def outer_check(time):
    def check_time(fn):
        def inner():
            fn()
        return inner
    return check_time

@outer_check(23)
def play_game():
    return '玩儿游戏'

play_game()

# 装饰器的高级用法 读取写入执行权限认证

使用情景
在函数前后需要填加其他操作,都可以使用装饰器

  • 引入日志
  • 函数执行时间统计
  • 执行函数前预备处理
  • 执行函数后清理功能
  • 权限校验等场景
  • 缓存
  • ...

欢迎各位大佬指点,有错留言,蟹蟹蟹蟹

你可能感兴趣的:(python栏 函数(递归/匿名/高阶/闭包/装饰器))