python全栈开发day12-函数的有用信息、带参数的装饰器、多个装饰器装饰一个函数、global和nonlocal的进一步解析和总结

1.上周回顾

  1)、函数名的应用

    直接打印函数名,是函数的地址

    变量

              函数的参数

              函数的返回值

              可以当容器类数据类型的元素

  2)、闭包

    内层函数对外层函数的非全局变量的引用,就是闭包。

    并返回内部函数或其结果给外部。

       3)、装饰器

import time
from functools import  wraps

def wrapper(f):
    @wraps(f)
    def inner(*args, **kwargs):
#       inner.__name__ = f.__name_
        #print(inner.__closure__)
        print('login执行前!',  f.__name__)
        ret = f(*args, **kwargs)
        print('login执行后!')
        return ret
    return inner
装饰器模板

 

2.函数的有用信息

  函数名.__name__

       函数名.__doc__

      

def login(username,password):
    """
    这是一个登陆函数,有两个参数
    :param username:
    :param password:
    :return:
    """
    print('登陆成功。。。。。')

print(login.__name__)
print(login.__doc__)
函数的有用信息,函数名和说明文档

 

3.带参数的装饰器

 

import time
def timer_out(flag):
    def timer(f):
        def inner(*args, **kwargs):
            #####
            if flag:
                start_time = time.time()
                time.sleep(0.3)
                ret = f(*args, **kwargs)
                end_time = time.time()
                print('用时%s秒!'% (end_time-start_time))
                ######
                return ret
            else:
                ret = f(*args, **kwargs)
                return ret
        return inner
    return timer


flag = False
@timer_out(flag)
def login(username,password):
    """
    这是一个登陆函数,有两个参数
    :param username:
    :param password:
    :return:
    """
    print('登陆成功。。。。。')


login(1,2)
带参数装饰器例子

 

4.多个装饰器装饰一个函数

 恰当的描述就是俄罗斯套娃!!

from functools import wraps


def wrapper1(f):
    @wraps(f)
    def inner1(*args, **kwargs):
        print('wrapper1,login执行前!')
        ret = f(*args, **kwargs)
        print('wrapper1,login执行后!')
        return ret
    return inner1


def wrapper2(f):
    @wraps(f)
    def inner2(*args, **kwargs):
        print('wrapper2,login执行前!')
        ret = f(*args, **kwargs)
        print('wrapper2,login执行后!')
        return ret
    return inner2


@wrapper2  #login = wrapper1(inner1)  ==inner2 login更新变量
@wrapper1  #login = wrapper1(login)  ==inner1   login新变量
def login():
    print('登陆成功!!!')


login()
"""
运行结果:
wrapper2,login执行前!
wrapper1,login执行前!
登陆成功!!!
wrapper1,login执行后!
wrapper2,login执行后!
"""
多个装饰器装饰一个函数的例子

 

 

5.global和nonlocal的进一步解析和总结

     局部作用域只能引用全局变量而不能修改,如要修改,必须要先声明global,同一层级作用域,全局变量的声明要放在最上面,否则会引起错误。

   子函数只能引用父函数的变量,而不能修改,如要修改,要nonlocal下。

def f1():
    global x
    print(x)

    # x = 15
    # print(x)
    def f2():
        global x
        x =100
        print(x)
    f2()
    print(x)
    # global x
    x = 300
    print(x)
f1()
print(x)
global引用实例

 

 

6.作业讲解收获知识点

  如果一个函数的默认参数是可变数据类型(如列表[]),无论使用多少次默认参数,都是一个。

def extendlist(var ,li=[]):
    li.append(var)
    return li


list1 = extendlist(10)
list2 = extendlist(123,[])
list3 = extendlist('a')

print(list1)
print(list2)
print(list3)
"""
运行结果:
[10, 'a']
[123]
[10, 'a']
"""
View Code

这个例子中函数第一次执行时,默认参数li = []是局部变量,执行完成后return后应该是li全局变量,赋值给list1就是全局变量了吧。

 

7.预习和拓展:

  迭代器和生成器:

  可迭代对象:

              拥有__iter__方法,惰性运算,range()、str、list、tuple、set、dict

       迭代器:拥有__iter__方法和__next__方法,

                   iter(range()),iter(str),iter(list),iter(tuple),iter(dict),iter(set),reversed(list_o),map(func,list_o),filter(func,list_o),file_o

       生成器表达式和生成器函数:

                  列表推导式中的【】换成()就是生成器表达式

                 函数中有yield和yield from的就是生成器函数。

  

 

posted @ 2018-05-15 20:48  富0代  阅读(121)  评论(0编辑  收藏  举报
返回
顶部