函数名 闭包 装饰器

函数名的应用(第一对象):
第一对象(first-class object)指
1,可在运行期创建
2,可用作函数参数或返回值
3,可存入变量的实体。
函数的应用:
1,直接打印函数名,得到的是函数的内存地址
def func1():
    print(666)
print(func1)   # func1没有(),只打印函数名,没有执行
View Code
2,函数名可以赋值运算
def func1():
    print(666)
f1 = func1
f1()   就等于func1() ,所以执行函数  #  666
View Code
3,函数名可以作为函数的参数。
def func1():
    print()
def func2(x):
    x()
    print(555)
func2(func1)   ###555
View Code
4,函数名可以作为容器类数据类型的元素。
def func1():
    print(666)
def func2():
    print(222)
def func3():
    print(111)
def func4():
    print(777)
lis = [func1 ,func2 ,func3 ,func4]
for i in lis:
    (i)
dic1 = {
    1:func1,
    2:func2,
    3:func3,
    4:func4,
}
dic1[1]()
View Code
5,函数名可当函数的返回值。
def func1():
    print(666)
def func2(x):
    print(222)
    return x
ret = func2(func1)
ret()  #    222    666
View Code
添加
l1 = []
for i in range(1,101):
    l1.append('func%d'%i)
print(l1)
View Code
闭包:
内层函数对外层函数非全局变量的引用就叫闭包。
在内层函数中访问外层函数的局部变量,叫闭包。这个时候局部变量将会常驻内存。 判断是不是闭包 函数名.
__closure__ 返回的None则不是闭包,返回的是cell...则是闭包
闭包的目的:让内存永远记住一个变量 闭包有什么用? 当执行一个函数时,如果解释器判断此函数内部闭包存在,这样python就一个机制,闭包的所在的临时名称空间不会随着函数的执行完毕而消失。
def func1():
    name = '老男孩'

    def inner():
        print(name)
    inner()
func1()
View Code
不是闭包
def func1():
    global name
    name = '老男孩'

    def inner():
        print(name)
    inner()
func1()
View Code
def func1(x):
    def inner():
        print(name)
    inner()
name = '老男孩'
func1(name)
View Code
判断是不是闭包:
闭包:
def func1():
    name = '老男孩'
    def inner():
        print(name)
    inner()
    print(inner.__closure__)
func1()  #<cell at 0x0000000001DF65B8: str object at 0x0000000001DF8BD0>
View Code
def func1(x):
    def inner():
        print(x)
    inner()
    print(inner.__closure__)
name = '老男孩'
func1(name)   
View Code
非闭包:
def func1():
    global name
    name = '老男孩'
    def inner():
        print(name)
    inner()
    print(inner.__closure__)  #None
func1()
View Code
def func():
    def func1():
        name ="老男孩"
    def func2():
        nonlocal name
        name = "alex"
    def func3():
        global name
        name = "太白"
    name = "日天"

    func1()
    print(name)  # 1 日天
    func2()
    print(name)  # 2,alex
    func3()
    print(name)  # 3,alex
func()
print(name)  # 4,太白
执行顺序
from urllib.request import urlopen
def index():
    url = "http://www.xiaohua100.cn/index.html"
    def get():
        return urlopen(url).read()
    return get
xiaohua = index()
content = xiaohua()
print(content)
爬虫一个网站

装饰器:

装饰器功能:在不改变原函数的基础上,为原函数增加一些额外的功能,log,登录注册,等等.
装饰器本质上就是一个python函数,他可以让其他函数在不需要做任何代码变动的前提下,增加额外的功能,装饰器的返回值也是一个函数对象。
装饰器的应用场景:比如插入日志,性能测试,事务处理,缓存等等场景

 

import time
def login():
    time.sleep(0.3)
    print('洗洗更健康...')

def timmer():
    start_time = time.time()
    login()
    end_time = time.time()
    print('此函数的执行时间%s' % (end_time - start_time))
timmer()
第一版本,测试函数low
import time
def login():
    time.sleep(0.3)
    print('洗洗更健康...')
# login()

def register():
    time.sleep(0.4)
    print('洗洗更健康22222...')
# register()
def timmer(f):
    start_time = time.time()
    f()
    end_time = time.time()
    print('此函数的执行时间%s' % (end_time - start_time))

timmer(login)
timmer(register)
改变了我原来执行函数的执行方式,不好
import time
def login():
    time.sleep(0.3)
    print('洗洗更健康...')
# login()

def timmer(f):
    start_time = time.time()
    f()
    end_time = time.time()
    print('此函数的执行时间%s' % (end_time - start_time))

f1 = login  # 将login函数名给了f1
login = timmer  # 将timmer函数名给了login
login(f1)  # timmer(login)
虽然执行函数的方式已经无限接近于原方式,但是更麻烦了,增加了两步代码。改
初级装饰器
import time
def login():
    time.sleep(0.3)
    print('洗洗更健康...')
# login()

def timmer(f):  # f = login函数名

    def inner():
        start_time = time.time()
        f()  # login()
        end_time = time.time()
        print('此函数的执行时间%s' % (end_time - start_time))
    return inner

login = timmer(login)  # inner 此login是新变量
login()  # inner()

name = 'alex'
name = '老男孩'
View Code
简单版装饰器  语法糖
import time
def timmer(f):  # f = login函数名
    def inner():
        start_time = time.time()
        f()  # login()
        end_time = time.time()
        print('此函数的执行时间%s' % (end_time - start_time))
    return inner

@timmer  # login = timmer(login)  # inner 此login是新变量
def login():
    time.sleep(0.3)
    print('洗洗更健康...')
login()

@timmer  # register = timmer(register)
def register():
    time.sleep(0.2)
    print('洗洗更健康22...')

login()  # inner()
View Code
被装饰的函数带参数的装饰器
import time
#
def timmer(f):  # f = login函数名
    def inner(*args,**kwargs):  # args (2, 3)
        start_time = time.time()
        f(*args,**kwargs)  # login() *(2, 3) 2,3
        end_time = time.time()
        print('此函数的执行时间%s' % (end_time - start_time))
    return inner

@timmer  # login = timmer(login)  # inner 此login是新变量
def login(a,b):
    print(a,b)
    time.sleep(0.3)
    print('洗洗更健康...')

login(2,3)  # inner(2,3)

@timmer  # register = timmer(register)
def register(a):
    time.sleep(0.2)
    print('洗洗更健康22...')

register(1)  # inner(1)

def func1(x):
    x = 0
    print(x)
func1(0)
View Code
函数带返回值的装饰器 (万能装饰器)
import time
def timmer(f):  # f = login函数名
    def inner(*args,**kwargs):  # args (2, 3)
        start_time = time.time()
        ret = f(*args,**kwargs)  # login() *(2, 3) 2,3
        end_time = time.time()
        print('此函数的执行时间%s' % (end_time - start_time))
        return ret
    return inner

@timmer  # login = timmer(login)  # inner 此login是新变量
def login(a,b):
    print(a,b)
    time.sleep(0.3)
    print('洗洗更健康...')
    return 666

print(login(2,3))  # inner(2,3)
View Code

简单版装饰器默写:

def wrapper(f):
    def inner(*args,**kwargs):
        '''执行被装饰函数之前的操作'''
        ret = f(*args,**kwargs)
        """执行被装饰函数之后的操作"""
        return ret
    return inner
View Code
语法糖装饰器默写:
def wrapper(f):
    def inner(*args,**kwargs):
        ret = f(*args,**kwargs)
        return ret
    return inner
@wrapper
def func():
    print(11)
func()
View Code
装饰器的本质是闭包。
开放封闭原则。
什么是开放封闭原则?
1.对扩展是开放的
    为什么要对扩展开放呢?
    我们说,任何一个程序,不可能在设计之初就已经想好了所有的功能并且未来不做任何更新和修改。所以我们必须允许代码扩展、添加新功能。
  2.对修改是封闭的
    为什么要对修改封闭呢?
    就像我们刚刚提到的,因为我们写的一个函数,很有可能已经交付给其他人使用了,如果这个时候我们对其进行了修改,很有可能影响其他已经在使用该函数的用户。
装饰器完美的遵循了这个开放封闭原则。
      
def wrapper(f): # f = func3函数名

    def inner(*args, **kwargs):
        print(333)
        ret = f(*args, **kwargs)  # func3(*(1,2))
        print(666)
        return ret  # 555
    return inner


# @wrapper  # func1新变量 = wrapper(func1) = inner
# def func1():
#     print(111)
# func1()  # inner()

# @wrapper  # func2(新变量) = wrapper(func2)      = inner
# def func2(a, b):
#     print(a, b)

# func2(1,2)  # inner(1,2)

@wrapper  # func3新变量 = wrapper(func3)     = inner
def func3(a, b):
    print(a, b)
    return 555

print(func3(2,3)) # inner(2,3)
View Code

 

 

posted on 2018-05-28 21:54  liangliang123456  阅读(210)  评论(0编辑  收藏  举报

导航