【1.1】函数即变量

在数字、字符串变量中,我们之前的数据类型文章中就说了,它是不可以修改的,因为它是放在内存堆中。如果修改就是新赋值,就是在内存堆中重新开辟了一个字符串/数字,然后把变量指向它;

字符串举例:

  如果有 x=1,y=x,那么这个时候, x 和 y都是引用指向 1 的内存地址,x 如果修改不影响 y。

       那么这个内存中的1什么时候被回收呢?  当该内存存储地址没有被任何变量、函数等引用指向的话,就会随着python默认的刷新检测机制检测发现没有任何引用,就会把它回收掉:

函数同理:

  那么同理,函数名也是一个引用指针,指向内存中存储函数体的这一块地址。这个我们从匿名函数形式 就可以比较直观的看出来;

【1.2】高阶函数

(1)把函数名做实参传给另外一个函数的形参(这也就表达了,高阶函数可以在不修改被装饰函数代码的情况下,为其添加功能)

(2)返回值中包含函数名(不修改函数的调用方式的情况下,为其添加功能)

【1.3】嵌套函数

嵌套函数,就是在函数的内部用def 定义另外的函数

【2】装饰器:基本形式(就是高阶函数+嵌套函数)

装饰器:本质上是函数,是用来装饰其他函数的(就是为其他函数添加附加功能)
原则(1):不能修改被装饰的函数的源代码
原则(2):不能修改被装饰的函数的调用方式
即:装饰器对函数来说是完全透明的,就是说函数感知不到装饰器的存在,也就函数的源代码和调用方式都没有被改变

(1)好理解的形式(无参数)

import time
def test1():
    time.sleep(3)
    print('in the test1')

def test2():
    time.sleep(3)
    print('in the test2')

def timer(func):  # timer(test1) func=test1
    def deco():
        start_time=time.time()
        func()  # run test1()
        stop_time=time.time()
        print('run the fun used {} second'.format(stop_time-start_time))
    return deco

test1 = timer(test1)
test1()

in the test1
run the fun used 3.0009162425994873 second

~~~实现了不修改函数源代码,也不修改函数调用方式,添加了新功能 输出函数执行使用时间

(2)语法糖:即用 @装饰器名  放到函数定义的上一行(带参数)

不带参数的函数也可以用 这种装饰器

import time
def timer(func):
    def warpper(*args,**kwargs):
        start_time=time.time()
        func(*args,**kwargs)
        stop_time=time.time()
        print('the func run time is {} '.format(stop_time-start_time))
    return warpper

@timer   # 这里实现了 test1 = timer(test1) 的功能
def test1(a,b,c):
    time.sleep(3)
    print('this is test1!')
    print(a,b,c)

test1(1,2,3)

this is test1!
the func run time is 3.000502824783325

(3)返回值的参数

import time
user, passwd = 'gg', '123456'
def auth(func):
    def wrapper(*args, **kwargs):
        username = input("Username:").strip()
        password = input("Password:").strip()
        if user == username and passwd == password:
            print("\033[32;1m User has passed authentication\033[0m")
            res = func(*args, **kwargs)
            print('函数运行完毕')
            return res
        else:
            exit("\033[31;1m Invalid Username or Password \033[0m")
    return wrapper

def index():
    print("welcome to index page")

@auth
def home():
    print("welcome to home page")
    return '我是home函数的返回值'

@auth
def bbs():
    print("welcome to bbs page")

index()
print(home())

welcome to index page
Username:gg
Password:123456
User has passed authentication
welcome to home page
函数运行完毕
我是home函数的返回值

(4)高潮迭起的装饰器:装饰器本身参数

# 根据装饰器参数,区分函数类别

user, passwd = 'gg', '123456'
def auth(auth_type):
    print("auth func type:",auth_type)
    def out_wrapper(func):
        def wrapper(*args, **kwargs):
            if auth_type == 'bbs':
                username = input("Username:").strip()
                password = input("Password:").strip()
                if user == username and passwd == password:
                    print("\033[32;1m User has passed authentication\033[0m")
                    res = func(*args, **kwargs)
                    print('函数运行完毕')
                    return res
                else:
                    exit("\033[31;1m Invalid Username or Password \033[0m")
            elif auth_type == 'home':
                print('自己直接访问就可以了啊,不需要做登录验证')
            else:
                print('又不是自己家,又不是bbs,滚蛋!')
        return wrapper
    return out_wrapper

def index():
    print("welcome to index page")

@auth('home')
def home1():
    print("welcome to home1 page")
    return '我是home1函数的返回值'
@auth('home')
def home2():
    print("welcome to home1 page")
    return '我是home1函数的返回值'

@auth('bbs')
def bbs1():
    print("welcome to bbs page")
@auth('bbs')
def bbs2():
    print("welcome to bbs page")

index()
home1()
bbs1()

auth func type: home
auth func type: home
auth func type: bbs
auth func type: bbs
welcome to index page
自己直接访问就可以了啊,不需要做登录验证
Username:gg
Password:123456
User has passed authentication
welcome to bbs page
函数运行完毕