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\n' % (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)

posted on 2018-05-16 19:22  kindle86  阅读(104)  评论(0编辑  收藏  举报

导航