• 0516Python基础-迭代器-生成器


    1、昨日内容回顾

        func.__name__

        func.__doc__

        带参数的装饰器

        def wrapper_out(*args, **kwargs):

            def wrapper(f):

                def inner(*args, **kwargs):

                    """执行被装饰函数之前的操作"""

                    ret = f(*args, **kwargs)

                    """执行被装饰函数之后的操作"""

                    return ret

                return inner

            return wrapper

    @wrapper_out('淘宝')

    def func1():

        pass

    def wrapper1(func):  func = f 函数名

        def inner1():

            print('wrapper1 ,before func')  # 2

            func()

            print('wrapper1 ,after func')  # 4

        return inner1

    def wrapper2(func): func = inner1

        def inner2():

            print('wrapper2 ,before func')  # 1

            func()

            print('wrapper2 ,after func')  # 5

        return inner2

    @wrapper2  # f = wrapper2(f) 里面的f是inner1  外面的f = inner2

    @wrapper1  # f = wrapper1(f) 里面的f是函数名  外面的f = inner1

    def f():

        print('in f')  # 3

    f()  # inner2()

    2、迭代器

        可迭代对象:内部含有__iter__

        迭代器:可迭代对象.__iter__()

        迭代器:内部含有__iter__且__next__

            判断 __iter__ 在不在dir(对象中)

            isinstance()

            节省内存。

            惰性机制。

            单向不可逆。

        for循环的机制:

            while

            pass

        可迭代对象

        迭代器

        两者区别

    模拟for循环机制

    迭代器

    可迭代对象

    s1 = '123'

    for i in s1:

        print(i)

    int  object is not iterable

    for i in 123:

        print(i)

    内部含有__iter__方法的就是可迭代对象,遵循可迭代协议。

    dir

    print(dir('123'))  # '__iter__'

    print('__iter__' in dir([1, 2, 3]))

    print('__iter__' in dir({'name':'alex'}))

    print('__iter__' in dir({'name'}))

    print('__iter__' in dir((1, 2, 3)))

    print('__iter__' in dir(1))  # False

    print('__iter__' in dir(True))  # False

    迭代器?可迭代对象通过.__iter__()可以转换成迭代器,满足迭代器协议。

    内部含有__iter__ 且 __next__方法的就是迭代器。

    l = [1, 2, 3]

    l_obj = l.__iter__()

    print(l_obj)

    迭代器的取值两种方法:

    方法一:__next__()

    print(l_obj.__next__())

    print(l_obj.__next__())

    print(l_obj.__next__())

    print(l_obj.__next__())

    方法二 for循环

    for i in l_obj:

        print(i)

    print('__next__' in dir(l_obj))

    第二种判断方式:

    from collections import Iterable

    from collections import Iterator

    print(isinstance('123', Iterable))

    print(isinstance('123', Iterator))

    实际上可迭代对象是不可以一个一个的一次取值的,因为他没有__next__方法。

    for循环提供一个机制:

    1,将可迭代对象转化成迭代器。

    2,利用__next__进行取值。

    3,用try异常处理方法防止报错。

    l = [1, 2, 3, 4, 5]

    l_obj = l.__iter__()

    while True:

        try:

            print(l_obj.__next__())

        except Exception:

            break

    迭代器:

    1,节省内存。

    2,满足惰性机制。

    3,取值过程不可逆(一条路走到黑)。

    3、生成器

        本质上是迭代器,用python代码构建的。

        生成器定义

        生成器的写法

        yield

    send

    生成器本质也是迭代器,生成器是自己用Python写的迭代器。

    1,通过生成器函数构建。

    2,通过生成器推导式构建。

    def func1():

        print(666)

        return 222

    ret = func1()

    print(ret)

    def func1():

        print(11)

        print(333)

        yield 222

        print(666)

        yield 777

    g_obj = func1()  # 生成器对象 generator object

    print(g_obj.__next__())

    print(g_obj.__next__())

    def cloth1():

        for i in range(1,10001):

            print('衣服%s' % i)

    # cloth1()

    def cloth2():

        for i in range(1,10001):

            yield '衣服%s' % i

    g = cloth2()

    for i in range(1,51):

        print(g.__next__())

    for i in range(1, 151):

        print(g.__next__())

    next  send

    def func1():

        count = yield 222

        print(count)

        yield 777

        yield 888

    g_obj = func1()  # 生成器对象 generator object

    # print(g_obj.__next__())

    print(g_obj.send('wusir'))

    1,send 具有next功能。

    2,send 可以给上一个yield传值。

    3, 第一个取值不能使用send.

    4,最后一个yield不会得到send的值。、

    4、作业讲解及知识点补充。

    1,装饰器:装饰器的本质是闭包。

    开放封闭原则。

    '''

    1.对扩展是开放的

        为什么要对扩展开放呢?

        我们说,任何一个程序,不可能在设计之初就已经想好了所有的功能并且未来不做任何更新和修改。所以我们必须允许代码扩展、添加新功能。

    2.对修改是封闭的

        为什么要对修改封闭呢?

        就像我们刚刚提到的,因为我们写的一个函数,很有可能已经交付给其他人使用了,如果这个时候我们对其进行了修改,

    很有可能影响其他已经在使用该函数的用户。

    装饰器完美的遵循了这个开放封闭原则。

    '''

    count = 1

    def func1():

        print(count)

    func1()

    局部作用域可以对全局作用域的变量进行引用。

    count = 1

    函数内部如果有变量名与全局变量名相同且对此变量进行改变,

    Python 就会将你引用的那个变量视为局部定义的变量,但是局部没定义,

    则他会报错。

    def func1():

        count1 = count + 1

        print(count)

    func1()

    def func1():

        count = 3

        def inner():

            count = count + 1

        inner()

        print(count)

    func1()

    函数中如果使用global + 变量 必须是第一次使用这个变量。

    flag = True

    def func1():

        if flag:

            print(333)

        global flag

        flag = False

    func1()

    flag = True

    while flag:

        print(333)

        flag = False

        print(222)

    for if while 没有开辟临时空间。

    globals() locals()

    locals :函数会以字典的类型返回 当前位置 的全部 局部变量。

    globals:函数以字典的类型返回全部全局变量。

    def extendList(val,list=[]):

        list.append(val)

        # print(globals())

        print(locals())  # {'list': [1], 'val': 1}

        def inner():

            a = 3

            b = 4

            print(locals())

        inner()

        return list

    ret = extendList(1)

    print(globals())  # 'ret': [1]

    print(locals())

    """

    给每个函数写一个记录日志的功能,

    功能要求:每一次调用函数之前,要将函数名称,时间节点记录到log的日志中。

    所需模块:

    import time

    struct_time = time.localtime()

    print(time.strftime("%Y-%m-%d %H:%M:%S",struct_time))

    """

    import time

    def wrapper(f):

        def inner(*args, **kwargs):

            with open('log', 'a', encoding='utf-8',) as f1:

                struct_time = time.localtime()

                time_now = time.strftime("%Y-%m-%d %H:%M:%S", struct_time)

                f1.write('在%s,执行了%s ' % (time_now, f.__name__))

            ret = f(*args, **kwargs)

            return ret

        return inner

    @wrapper

    def func1():

        time.sleep(2)

        print(666)

    @wrapper

    def func2():

        time.sleep(0.1)

        print(666)

    @wrapper

    def func3():

        time.sleep(0.3)

        print(666)

    func1()

    func3()

    func2()

     

    5、列表推导式、生成器表达式

     

           列表推导式:能用列表推导式完成的,用python代码都可以完成。

    用一句话构建一个你想要的列表。

    优点:简单,稍微难理解。

    缺点: 不能用debug。

    li = []

    for i in range(1, 12):

        li.append(i)

    print(li)

    li = [i for i in range(1, 12)]

    [ 变量(加工后的变量) for 变量 in 可迭代对象 ]  遍历模式

    print(li)

    li = []

    for i in range(1, 12):

        li.append('python%s期' % i)

    print(li)

    li = ['alex', 'wusir', 'taibai', 'nvshen', 'ritian']

    li = ['python%s期' % i for i in range(1, 12)]

    print(li)

    l2 = [i+'_NB' for i in li]

    print(l2)

    [ 变量(加工后的变量) for 变量 in 可迭代对象 ]  遍历模式

    [ 变量(加工后的变量) for 变量 in 可迭代对象 if 判断]  筛选模式

    l1 = [i for i in range(1, 101) if i % 2 == 0]

    print(l1)

    1,筛选,100以内所有的奇数。

    l2 = [i for i in range(1, 101) if i % 2 == 1]

    l2 = [i for i in range(1, 101, 2)]

    print(l2)

    2,10以内所有数的平方。 [1,4,9,16.。。100]

    print([i*i for i in range(1, 11)])

    3,将100以内所有内被三整除的数留到列表中。

    print([i for i in range(1,101) if i % 3 == 0])

    g = (i*i for i in range(1, 11))

    # print(g.__next__())

    # print(g.__next__())

    for i in g:

        print(i)

    列表推导式 简单明了,但是占内存

    生成器表达式 节省内存,不易看出。

    30以内所有能被3整除的数的平方

    print([i*i for i in range(1, 31) if i % 3 ==0])

    names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],

             ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]

    l3 = [ name for i in names for name in i if name.count('e') == 2]

    print(l3)

    mcase = {'a': 10, 'b': 34}

    mcase_frequency = {mcase[k]: k for k in mcase}

    print(mcase_frequency)

  • 相关阅读:
    Bootstrap JS插件使用实例(2)-模态对话框
    Java常用正则表达式验证工具类RegexUtils.java
    程序员不是砌砖工人,他们是作家【转】
    js中继承的几种用法总结(apply,call,prototype)
    javascript中apply()方法解析-简单易懂!
    javascript方法 call()和apply()的用法
    高性能优化Web前端
    Javascript类继承-机制-代码Demo【原创】
    初识WEB:输入URL之后的故事【转】
    博客园添加网站统计访问量-操作简单很实用哦!
  • 原文地址:https://www.cnblogs.com/dzh0394/p/9047681.html
Copyright © 2020-2023  润新知