Python Day13-14

一.上周回顾复习·

  函数:

1.函数名的本质  —— 就是一个变量 里面存储了函数的内存地址   函数名可以作为函数的参数、返回值。可以被赋值,可以作为可变数据类型的元素

2.函数的定义

~参数——形参:

        位置参数

  *args

  默认参数

  **kwargs

~返回值 return

  返回值为None

  返回一个值,这个值可以是任意数据类型

  返回多个值,多个值之间用逗号隔开,以元组的形式返回

3.函数调用

~参数——实参:

  按照位置传参

  按照关键字传参

~获取返回值

  接收返回值

  不接受返回值    

4.函数的应用 ——闭包函数

  在内部函数中使用了外部函数的变量,这个内部函数就叫做闭包

5.作用域——全局作用域,局部作用域

  全局作用域内的变量可以被局部作用域使用

 a = 1
 def func():
     print(a)

 func()

输出结果
1

  在局部作用域内定义的变量不能在全局作用域使用

 def func_b():
     b = 20   #b是局部作用域中的变量

 func_b()
 print(b)    #报错:在全局作用域中不能使用局部作用域的变量

  关于global关键字:

c = 10
def func_c1():
    c = 20
    print('in func_c1',c)
func_c1()
print(c)
输出结果
in func_c1 20
10

加入global关键字以后:

c = 10
def func_c2():
    global c
    c = 20
    print('in func_c2',c)
func_c2()
print(c)
输出结果
in func_c2 20
20

~命名空间:内置、全局、局部

6.装饰器  —— 函数的应用

#def wrapper(func):
# def inner(*args,**kwargs):
# '''在执行被装饰的函数之前要做的事情'''
# ret = func(*args,**kwargs)
# '''在执行被装饰的函数之后要做的事情'''
# return ret
# return inner     (必背!)

 

@wrapper 
def func():
pass        @wrapper 语法糖表示 func = wrapper(func)

.迭代器

1.迭代器 就是实现了能从其中一个一个的取出值来

~只要包含了“双下iter”方法的数据类型就是可迭代的 —— 可迭代协议
数据类型和python解释器定下来的协议

~'__iter__'   这个方法导致了一个数据类型的可迭代

~迭代器中有 __next__ 和 __iter__方法  —— 迭代器协议

~在python里 你学过的所有的可以被for循环的 基本数据类型 都是可迭代的 而不是迭代器

lst_iterator = [1,2,3].__iter__()
print(set(dir(lst_iterator)) - set(dir([1,2,3])))

输出结果


{'__length_hint__', '__setstate__', '__next__'}

2. 可迭代对象

~可迭代协议:含有__iter__方法的对象

~迭代器协议:含有__iter__和__next__方法的对象

3.迭代器和可迭代对象之间的关系

~可迭代对象包含迭代器 

  那么可迭代对象是如何成为迭代器的? 

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

**可迭代对象并不能用,它是变成迭代器以后才能用的

    怎么用呢?

  

lst_iterator = [1,2,3].__iter__()
print(lst_iterator.__next__())
print(lst_iterator.__next__())
print(lst_iterator.__next__())  
#迭代器中[1,2,3]打印三个没有了再打印就会报错
输出结果

1
2
3

~for 可以是一个可迭代对象 也可以是一个迭代器

  如果 for循环的内容是一个可迭代的对象时,它就会自动的去调用可迭代对象的__iter__方法获取到一个迭代器

~为什么要有迭代器 迭代器存在的本质是什么:

   1.能够对python中的基本数据类型进行统一的遍历,不需要关心每一个值分别是什么
   2.它可以节省内存 —— 惰性运算

   f = open('file','w')     文件句柄就是一个迭代器

  range(10000000).__iter__()   range就是一个可迭代的对象

~迭代器:

    1.天生的,比如文件句柄

   2.后天的,可迭代对象.__iter__()

三.  生成器  Iterator 迭代器  Gerator 生成器

1.生成器就是迭代器,生成器是我们自己写出来的

2.生成器分类

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

  ~生成器表达式:类似于列表推导,但,生成器返回按需生产结果的一个对象,而不是一次构建一个结果列表。

3.什么时候用到生成器??

   当创建列表只是一共中间过程的时候,为了避免创建庞大的列表,我们可以使用生成器表达式来完成

  • 生成器是可迭代对象;
  • 实现了延迟计算,省内存(按需执行);
  • 生成器本质和其他类型一样,都是实现了迭代器协议,只不过生成器是一边计算,一边生成,从而节省内存空间,其余的可迭代对象可没有这个功能。
def generator_func():  #生成器函数
    print(123)
    yield 'aaa'   #return
    print(456)
    yield 'bbb'
g = generator_func()        #generator生成器  - 生成器的本质就是迭代器
ret = g.__next__()
print(ret)
ret2 = g.__next__()
print(ret2)
g = generator_func()
print(list(g))

输出结果

123
aaa
456
bbb
123
456
['aaa', 'bbb']

**带yield关键字的函数就是生成器函数

**生成器函数在执行的时候只返回一个生成器,不执行生成器函数中的内容

**从生成器中取值:

  1.__next__ 有几个yield就可以取几次
  2.for循环取值 正常取 for i in g:
  3.其他数据类型进行强制转换 list(g) 返回一个列表,里面装着生成器中的所有内容
  注意:调用生成器函数的时候,要先获取生成器,再进行next取值
    生成器中的内容只能取一次,且按顺序取值没有回头路,取完为止。

def generator():
    yield
    yield 2
g = generator()
for i in g:
    print(i)

输出结果

none

2

进阶示例

def get_clothing():
    for cloth in range(1,2000000):
        yield '第%s件衣服'%cloth
g = get_clothing()
print(g.__next__())
for i in range(20):
    print(g.__next__())


输出结果

第1件衣服
第2件衣服
第3件衣服
第4件衣服
第5件衣服
第6件衣服
第7件衣服
第8件衣服
第9件衣服
第10件衣服
第11件衣服
第12件衣服
第13件衣服
第14件衣服
第15件衣服
第16件衣服
第17件衣服
第18件衣服
第19件衣服
第20件衣服
第21件衣服
import time
def tail(filename):
    f = open(filename,encoding='utf-8')
    f.seek(0,2)   #将文件的光标移到最后
    while True:
        line = f.readline()
        if not line:
            time.sleep(0.1)
            continue
        yield line

tail_g = tail('demo')
for line in tail_g:
    print(line,end='')

四.最后的总结:

1.可迭代对象   内部有__iter__

2.迭代器    内部有__iter__ __next__

3.生成器 就是迭代器

自己写的迭代器
生成器函数 yield /yield from
生成器表达式

def generator_func(): #生成器函数
print(123)
yield 'aaa' #return
print(456)
yield 'bbb'

    



 

    

     

原文地址:https://www.cnblogs.com/liuduo/p/7474279.html