随堂笔记20day

生成器总结

  1.语法上和函数类似,生成器函数和常规函数几乎是一样的。他们都是使用def语句进行定义,差别在于,生成器多次使用yield语句返回一个值,而常规函数使用一次return语句返回一个值。

  2.自动实现迭代器协议,对于生成器,python会自动实现迭代器协议,以便应用到迭代背景中(如for循环,sum函数)。由于生成器自动实现了迭代器协议,所以,我们可以调用它的next方法,并且,在没有值可以返回的时候,生成器自动产生stoplteration异常

  3.状态挂起,生成器使用yield语句返回一个值,yield语句挂起该生成器函数的状态,保留足够的信息以便之后从它离开的地方继续执行。

函数可以理解成用来描述一个过程

什么是迭代器协议*****************忘记了,记得不够牢固

生成器只能遍历一次,这个很重要,我出错好几次都是因为这个原因

生成器表达式

  g_l = ('a' for i in range(10) )  ---圆括号

列表解析

  l = [ 'a' for i in range(10) ] -----方括号

def test():
    for i in range(4):
        yield i

t = test()


t1 = ( i for i in t)
print(list(t1) )

结果[0, 1, 2, 3]

大前提:生成器产生的时候,不会进行任何操作,生成器取值是通过next方法

生成器只能走一遍(遍历一次)*****重要的事情说三次

t1 = ( i for i in t )

t2 = ( i for i in t1)

print(list(t1)) *******因为 t1 取空了,所以 t2 取不到值

print(list(t2))

结果

[ 0, 1, 2, 3 ]

[ ]

----------------------------------

l = [1, 2,3 ]

变成可迭代对象

l.__iter__() 也可以是 iter(l)

--------------------------

装饰器

装饰器本质就是函数,功能是为其他函数添加附加功能

原则是:

  1不修改被修饰函数的源代码 ------------------(源代码被修改,有可能会产生不可预知的变化,因为你不知道源代码会在哪里被调用)

  2不修改被修饰函数的调用方式

装饰器的知识储备:

  装饰器 = 高阶函数 + 函数嵌套 + 闭包

高阶函数的定义:

  1.函数接收的参数是一个函数名

  2.函数的返回值是一个函数名

  3.满足上述条件任意一个,都可称之为高阶函数

课上案例1

import time

l = [1,2,3,4]

def cal():
    start_time = time.time()
    time.sleep(2)
    ret = 0
    for i in l:
        ret += i
    stop_time = time.time()
    print('这是程序运行时间为%s'%(stop_time-start_time))
    return ret

cal()
结果
这是程序运行时间为2.0003061294555664

高阶函数

def test(func):
    print(func)
    func()
test(func)

添加时间功能

import time

def foo():
    print('你好啊,海绵宝宝')

def test(func):
    print(func)
    start_time = time.time()
    func()
    stop_time = time.time()
    print('这是程序运行时间为%s' % (stop_time - start_time))

test(foo)
结果:
<function foo at 0x0000018662ED1E18>
你好啊,海绵宝宝
这是程序运行时间为0.0

test(foo)这样是违反里不改变函数调用方式,原来调用方式是foo()

返回值是一个函数(高阶函数) 

def foo():
    print('from the foo')

def test(func):
    return func

res = test(foo)
print(res) ------------打印的是foo的内存地址
res()       -----------运行foo函数

高阶函数的两个功能结合(因为多运行了一次foo,所以不合格)

import time

def foo():
    time.sleep(3)
    print('来自foo')

def timmer(func):
    start_time = time.time()
    func()
    stop_time = time.time()
    print('这是程序运行时间为%s' % (stop_time - start_time))  再写的时候报错是因为括号是中文模式写的
    return func
foo = timmer(foo)
foo()

结果

来自foo
这是程序运行时间为3.000319004058838
来自foo

函数嵌套:函数内部再定义一个函数

函数嵌套例子:

def fater(name):
    print('父亲的名字是%s'%name)
    def son():
        print('from  son')
        def granson():
            print('from granson')
        granson()
    son()
fater('海绵宝宝')

结果

父亲的名字是海绵宝宝
from  son
from granson

局部变量的寻找

def fater(name):
    print('父亲的名字是%s'%name)
    def son():
        print('我爸爸是'+ name)
    print(locals())    ----------打印当前局部变量

fater('海绵宝宝')

结果
父亲的名字是海绵宝宝
{'son': <function fater.<locals>.son at 0x000002851DB25510>, 'name': '海绵宝宝'}

其中son是内存地址

----------------------------------------------------------------------------------------------------------------------------------- 

补充的知识点(在终端cmd模式演示)

一行赋值多个值------(解压序列,一 一对应的关系)

>>>>>> a,b,c = (1,2,3)

>>>>>>a

             1

>>>>>>b

             2

>>>>>>c

             3

去开头和结尾的数字(终端演示) 

l  = [ 10, 2, 30, 47, 4, 6, 87, 45 ]

a,*_,c = l

>>>>>>a

     10

>>>>>>c

     45

>>>>>>>_                  (下划线代表中间所有元素)

    2, 30, 47, 4, 6, 87

也可以是这样

a,b,*_,c,d = l

>>>>>>a

     10

>>>>>>b

     2

>>>>>>c

     87

>>>>>>d

     45

取开头和结尾(索引方式)

a,d = l[0], l[-1]

a和b的值互换

a = 1      b = 2

第一种方法

x = a

a = b

b = x

第二种方法

a, b = b, a

--------------------------------------------------------------------------

这个是我们想要修饰器做到的效果,只运行一次。

import time
def timmer(func):
    def wrapper():
        start_time = time.time()
        func()
        stop_time = time.time()
        print('这是程序运行时间为%s' % (stop_time - start_time))
    return wrapper

def test():
    time.sleep(3)
    print('test程序运行完毕')

res = timmer(test)            返回的是wrapper的内存地址
res()                         这里执行的是wrapper()

结果

test程序运行完毕
这是程序运行时间为3.000622272491455

然后调用方式改一下,就是我们要修饰器要达到的效果。

import time
def timmer(func):
    def wrapper():
        start_time = time.time()
        func()
        stop_time = time.time()
        print('这是程序运行时间为%s' % (stop_time - start_time))
    return wrapper

def test():
    time.sleep(3)
    print('test程序运行完毕')

test = timmer(test)            返回的是wrapper的内存地址
test()                         执行的是wrapper()

结果
test程序运行完毕
这是程序运行时间为3.0006837844848633

可以在要修饰的函数前写上  @timmer   就相当于 test= timmer(test)

                                           写的时候出错有两点:

                                                    1.函数名称写错(没有技术含量的错误)

                                                    2.在修饰器的返回值那里return wrapper 写成 return wrapper()

 

加上返回值,加上参数。要求

加上参数:(*args, **kwargs)用来接收不确定参数格式

验证功能大型例子

第一次写

# name = 'bili'
# pawd = 123
#为了纪念伟大的bili

# shopping_car_list = ['皮鞭','蜡烛','内裤']
'''
现在是要在所有的程序前面加上用户验证,利用装饰器功能。
'''
def zsq(func):       #装饰器
    def yhyz(*args,**kwargs):   #用户验证
      name = input('请输入用户名字').strip()#应该是除去空白
      pawd = input('请输入密码').strip()
      if name == 'bili' and pawd == '123':   #出现一次缩进错误
          print('欢迎进入哲学天堂')
          func()                 #***********忘记写了
      else:
          print('密码或者用户名错误')
    return  yhyz
                                   #问题一为什么只是在index()里,没有进入下一层
                                                    #少了一步是运行该函数func()
                                    #问题二,为什么没有将名字传给index()里
@zsq
def index():  #程序的主页
    print('欢迎%s来到哲学天堂')

@zsq
def home():   #用户的家目录,也可以理解成个人信息设置
    print('请完善%s信息')

@zsq
def shopping_car():   #购物车
    print('你的购物车有皮鞭,蜡烛,内裤')  #怎么传一个列表给购物车


index() home() shopping_car()

 #问题二,为什么没有将名字传给index()里,是因为引用方法不对

+用户只需要登入一次功能

+用户名称显示在其他被修饰程序中功能

#问题二,为什么没有将名字传给index()里
#错误显示没有找到name,index应该是要找全局变量的
dic_user = {'name': None, 'login': False}    #定义一个全局变量来保存登入状态


def zsq(func):  # 装饰器
    def yhyz(*args, **kwargs):  # 用户验证
        if dic_user['name'] and dic_user['login']:       #如果之前登入过了就不用再登入了,这句话是真的情况下
            ret = func(*args, **kwargs)
            return ret
        name = input('请输入用户名字').strip()
        pawd = input('请输入密码').strip()
        if name == 'bili' and pawd == '123':
            dic_user['name'] = name
            dic_user['login'] = True
            print('欢迎进入哲学天堂')
            ret = func(*args, **kwargs)
            return ret
        else:
            print('密码或者用户名错误')

    return yhyz


@zsq
def index(*args, **kwargs):  #程序的主页                  
    print('欢迎%s来到哲学天堂'%dic_user['name'])           #这里要变量要到全局的找,之前一直失败是因为这里找的不对

@zsq
def home():   #用户的家目录,也可以理解成个人信息设置
    print('请完善%s信息')

@zsq
def shopping_car():   #购物车
    print('你的购物车有皮鞭,蜡烛,内裤')     #这么传一个列表给购物车,这个列表是一个保存大一个文件里,当是bili登入时才显示。           **这个功能下次写吧**

index()


print(dic_user)

+用户不在是一个人,而是多个。

user_id = [
    {'name': 'nec', 'pawd': '123'},#nec老中医,战场搅屎棍
    {'name': 'aoe', 'pawd': '123'},
    {'name': 'bili', 'pawd': '123'},
    {'name': 'acfun', 'pawd': '123'},
]
dic_user = {'name': None, 'login': False}


def zsq(func):  # 装饰器
    def yhyz(*args, **kwargs):  # 用户验证
        if dic_user['name'] and dic_user['login']:
            ret = func(*args, **kwargs)
            return ret
        ipname = input('请输入用户名字').strip()
        ippawd = input('请输入密码').strip()

        for i in user_id:
            if ipname == i['name'] and ippawd == i['pawd']:   #这里出错了TypeError: list indices must be integers or slices, not str
                dic_user['name'] = ipname                     #类型错误:列表索引必须是整数或片,而不是str。
                dic_user['login'] = True                      #不应该时user_id 而是 i才对,i才是元素,而user_id是整个列表
                print('欢迎进入哲学天堂')
                ret = func(*args, **kwargs)
                return ret
        else:
            print('密码或者用户名错误')

    return yhyz


@zsq
def index():  #程序的主页
    print('欢迎%s来到哲学天堂'%dic_user['name'])

@zsq
def home():   #用户的家目录,也可以理解成个人信息设置
    print('请完善%s信息'%dic_user['name'])

@zsq
def shopping_car():   #购物车
    print('你的购物车有皮鞭,蜡烛,内裤')  

用户登入类型(懒)

原文地址:https://www.cnblogs.com/chrpy/p/8546659.html