1.迭代器和生成器


迭代器

 

        迭代器对象要求支持迭代器协议的对象,在Python中,支持迭代器协议就是实现对象的__iter__()和__next__()方法。

        其中__iter__()方法返回迭代器对象本身;__next__()方法返回容器的下一个元素,在结尾时引发StopIteration异常。

 

#迭代器 iterator

li = [1,2]

del li

 

li = []

##for i in range(11):

##    if i%2==0:

##        li.append(i)

 

for i in range(0,11,2):

      li.append(i)

class TupleIter:

       def __init__(self,li):

              self.li = li

              self._index = 0

       def __iter__(self):

              return self

       def __next__(self):

             if self._index < len(self.li):

                   index = self.li[self._index]

                   self._index += 1

                   return index

            else:

                   raise StopIteration

 

tu = TupleIter((1,2,3,4,5))

 


生成器

 

        在Python中,使用生成器可以很方便的支持迭代器协议。

 

        生成器通过生成器函数产生,生成器函数可以通过常规的def语句来定义,但是不用return返回,而是用yield一次返回一个结果,在每个结果之间挂起和继续它们的状态,来自动实现迭代协议。

    

        也就是说,yield是一个语法糖,内部实现支持了迭代器协议,同时yield内部是一个状态机,维护着挂起和继续的状态。

 

        生成器函数返回生成器的迭代器。 “生成器的迭代器”这个术语通常被称作”生成器”。

 

        要注意的是生成器就是一类特殊的迭代器。作为一个迭代器,生成器必须要定义一些方法,

 

        其中一个就是__next__()。如同迭代器一样,我们可以使用__next__()函数来获取下一个值。

    

        在一个 generator function 中,如果没有 return,则默认执行至函数完毕,如果在执行过程中 return

 

        则直接抛出 StopIteration 终止迭代。 

 

def fun(n):

       i = 0

       while i < n:

              print('***',i)

              yield i

              i += 1

              print('+++',i)

 

a = fun(5)

 

"""

yield可以暂停函数的执行,所以可以占用很少的空间,不会一直占用很大的内存

"""

import time

def run_time(func):

      def new_fun(*args):

             t0 = time.time()

             print('star time: %s'%(time.strftime('%x',time.localtime())) )

             back = func(*args)

             print('end time: %s'%(time.strftime('%x',time.localtime())) )

             print('run time: %s'%(time.time() - t0))

             return back

      return new_fun

 

@run_time

def fab(maxnu):

       n,a,b = 0,0,1

       while n < maxnu:

              print(b)

              a,b = b,a+b

              n = n+1

##@run_time

def fab2(maxnu):

       n,a,b = 0,0,1

       while n < maxnu:

              yield b

              a,b = b,a+b

             n = n+1

 

b = fab2(100)

next(b) # next(b) 就是next函数调用 b 的 __next__() return b.__next__()

 

列表推导式

 

#列表推导式

l2 = [i for i in range(11)]  

l3 = [i for i in range(11) if i%2 == 0 ]

l4 = [i*2 for i in range(11) if i%2 == 0]

 

{i for i in range(10)}

{i:str(i) for i in range(10)}

 

[i if i%2==0 else str(i) for i in range(10)]

 


  2.模块和包


1)内置模块

 

        本身就带有的库,就叫做Python的内置的库。(模块==库)

        一些常见的内置模块

        os 和操作系统相关     os.path

        sys 和系统相关      sys.path  

        sys.path.append(r'')    可以添加路径

        re  正则表达式 

    

2)第三方模块

 

        非Python本身自带的库,就是所谓的第三方的库

        

3)模块的导入

 

        import xxx  [as  yy]

        from ../xx  import  xx  [as  yy]  

        

4)自定义模块

 

        py文件,可以做为一个模块来用,直接作为一个模块导入就行

    __main__ 的意义:

 

        当文件是直接运行是,文件的__name__是__main__ ,当文件是被导入时,__name__是文件名

 

5)包管理

 

        基本上就是另外一类模块。把用来处理一类事物的多个文件放在同一文件夹下组成的模块集。

 

        要让python 将其作为包对待,在python2中必须包含__init__.py的文件,但在python3中没有__init__.py文件也可以,使用包可以避免多个文件重名的情况,不同的包下的文件同名不影响。

        

        导入包和模块是一样的方法,包导入后会在目录中自动生成__pycache__文件夹存放生成的.pyc文件,要注意的是import后面的才是存在当前作用域中的对象名,from是告诉python从什么地方导入,

 

        使用sys.path添加文件的目录路径。

 

#模块和包

##import keyword  #内置模块

##keyword.kwlist

 

#模块就是一个py文件

##from keyword import kwlist as yy #导入你需要的

from keyword import kwlist,main

 

 

#同目录下

import test

__name__

 

 

#不同路径下

import os,sys

 

sys.path

sys.path.append(r'C:\Users\不动\Desktop\Python基础\4面向对象\02多继承,类的特殊方法,装饰器')

 

import test1

##from test1 import ...

 

if __name__ == '__main__':

     print(__name__)

     sys.argv

     print(sys.argv)

##    print('******',sys.argv[1])

 

#包

#包就是把很多模块放在一起

##import xml

##import xml.dom.xmlbuilder