Python面试必考:装饰器、迭代器、生成器

python面试三大器:

  1. 迭代器
  2. 生成器
  3. 装饰器 : @skip类似于这种

 迭代器:

迭代:for 循环从列表[1,2,3]中取元素,这种遍历过程就被称作迭代

可迭代的对象有:字符串、元祖、列表、字典这类集合元素可以进行迭代处 可迭代的对象里面

a = [1, 2, 3]
for i in a:
    print(i)

    上述例子中,for 循环怎么知道谁是可迭代的对象呢?换个说法,我们的对象需要满足什么样的条件,就可以被for循环一个一个的取出来呢?我们就必须满足for的要求,这个要求就叫做“协议”!!

所谓协议就是类的内部实现了_iter()__和__next()__方法这两个魔法方法或者特殊方法,

只要实现了这两个特殊方法,这个对象就是可迭代的对象。可以被循环可以被迭代

当执行一个for循环的时候,迭代一个列表时,底层到底做了什么呢,

Python面试必考:装饰器、迭代器、生成器_第1张图片

调用可迭代对象__inter__方法返回一个迭代器对象,(iterator)

不断调用迭代器__next__方法返回元素 

直到迭代完成后,处理StopIteration

我们用上述方法实现一下:

a = [1, 2, 3]
aa = iter(a)
while True:
    print(next(aa))

结果:

Python面试必考:装饰器、迭代器、生成器_第2张图片

改进,使用try,catch捕获异常 

a = [1, 2, 3]
aa = iter(a)
while True:
    try:
        print(next(aa))
    except StopIteration:
        break

和for循环的结果一样:效率比for循环高一点

Python面试必考:装饰器、迭代器、生成器_第3张图片

iter() : 这个方法可以把任何一个可迭代对象转成迭代器,然后使用next的方法去循环取元素

迭代器(Iterator) :  迭代器是一个可以记住遍历位置的对象,迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束,迭代器往前不会后退!!

类型转换:

  • 可迭代对象 ————>迭代器 iter()
  • 迭代器 ----------> 集合数据类型list() tuple() str()

如何把一个迭代器转回成一个列表或者字典呢??????python 的高阶函数经常有,例子

a = [1, 2, 3]
print(map(lambda x: x ** 2, a))

结果,

为什么返回了迭代器,而不是一个列表呢 ? 会的到一个迭代器对象,而不是内容本身,惰性算法推倒时,会节省大量的内存空间,用一个生产一个,好处就是,执行效率高、节省内存资源、提升语言的性能

在python2 中会直接得到1,4,9,但是在python3中就不是这样了,返回的是一个迭代器

为什么python中返回一个迭代器而不是列表??

迭代器是不会占用内存空间的,返回的是一个列表式,是一个算法,告诉你数据是怎么生成的,需要的时候会被执行生成

for i in map(lambda x: x ** 2, a):
    print(i)

返回:

1
4
9

 python3最重要的变更是:返回迭代器,而不是内容本身,节省内容空间,提升语言性能

判断一个对象是否是迭代器或可迭代对象

from collections.abc import Iterator, Iterable
xx = [1, 2, 3]
bb = map(lambda x: x ** 2, xx)
print(isinstance(xx, Iterable))
print(isinstance(xx, Iterator))
print(isinstance(bb, Iterable))
print(isinstance(bb, Iterator))

 结果:

Python面试必考:装饰器、迭代器、生成器_第4张图片

应用场景

  1.  迭代器是惰性计算的程序流,他没有数据,你需要下一个元素,它就按照算法给你计算出下一个元素返回,等到无法计算出下一个元素       时,将引发StopIteration异常,所以可迭代对象只能表示有限的元素个数,而迭代器甚至可以表示整个自然数集合。             --节省内存空间
  2. 循环用到的range(),其实就是一个迭代器,比如range(1000),不是生成一个1000个元素的集合,而是内置了next函数,逐个生成
  3. 文件调用的时候,file.readlines(),是返回了一个列表,而for line in file:则是迭代器中逐行前进,也是内置了next函数

 如何定义一个可迭代的对象??例子

class Classes(object):
    """
    班级类
    """
    def __init__(self, number):
        self.number = number
        self.students = []
        self.n = 0

    def add(self, name, age):
        self.students.append((name, age))

a = Classes('1-1')
a.add('张三', 7)
a.add('李四', 3)

for i in a:
    print(i)

结果提示,这个对象不是可迭代的

 现在我们改动一下,把他改成一个可迭代对象如图:

实现__iter__和__next__方法的对象都是迭代器,__iter__返回的是迭代器自身,__next__返回容器的下一个数值

class Classes(object):
    """
    班级类
    """
    def __init__(self, number):
        self.number = number
        self.students = []
        self.n = 0

    def add(self, name, age):
        self.students.append((name, age))

    def __iter__(self):
        return self

    def __next__(self):
        if self.n < len(self.students):
            n = self.n
            self.n += 1
            return self.students[n]
        else:
            raise StopIteration


a = Classes('1-1')
a.add('张三', 7)
a.add('李四', 3)

for i in a:
    print(i)

结果:

 ========================================================

生成器

解释:通过列表生成式,我们可以直接创建一个列表,但是受到内存的限制,列表容量肯定式有限的,而且我们创建100万个元素的列表,不仅占用很多内存空间,如果我们访问前几个,那么后面很大的内存空间白白浪费了,

所以如果列表元素可以按照某种算法推算出来,我们是否可以在循环的过程中不断推断后续的元素

这样可以不必创建完整的list,从而节省很大的空间,在python中一边循环一边计算的机制,被称为生成器

生成器也是一种迭代器,但是只能对其迭代一次,这是因为他们并没有把所有的值存储在内存中,而是运行时生成值

列表生成式,一行表示出来,以下等价

a = [i for i in range(0, 10)]

a = []
for i in range(0,10):
    a.append(i)

 生成器的一个例子:

# 列表生成器
a = [i for i in range(0, 10)]
print(type(a))
# 生成器表达式
b = (i for i in range(0, 10))
print(type(b))

 打印结果:

 当生成算法比较复杂时,我们需要准备一个函数,生成器函数,用yield代替return:

  • 把函数的结果做生迭代器
  • 函数暂停与再继续允许的状态是有yield

例子,原始写法和生成器写法对比:生成器特点:

代码行数更少,代码更易读,时效更高,占用空间更小 

Python面试必考:装饰器、迭代器、生成器_第5张图片

 ========================================================

装饰器

1: 装饰器是用来装饰函数的,可能是原始函数不太丰富

首先先了解以下闭包的含义:

首先函数的参数可以是函数---------高阶函数,

函数的内部可以定义函数--------内部函数

但是外部的构造者无法访问内部的函数,这个就叫做闭包

例子:

def print_msg():
    msg = "i m closur"

    def printer():
        print(msg)
    return printer

结果:

外部函数最终将内部函数返回,完成了调用!!!!!!!!!! 

Python面试必考:装饰器、迭代器、生成器_第6张图片

例子:

# 函数,用来装饰其他的函数,其他函数征文执行之前或者之后,执行一些代码逻辑
def A(fun):
    def printer():
        print("双11机器人5折开始")
        fun()
        print("双11机器人5折结束")

    return printer


@A
def say_hello():
    print("您好")

@A
def goodbye():
    print("在家")


say_hello()

结果:

Python面试必考:装饰器、迭代器、生成器_第7张图片

 

 

你可能感兴趣的:(python)