第一类对象\闭包\迭代器

1.第一类对象

  函数名----->变量名

    (1)函数对象可以像变量一样进行赋值.

          def fn():

            print("我叫fn")

          gn=fn              #函数名可以进行赋值

          gn()

             比较:   fn=666

           print fn

    (2)可以像列表元素一样使用

                                  def fun1():

 

            print("朱祁镇")

 

          def fun2():

 

            print("徐阶")

 

          def fun3():

            print("王阳明")

          lst=[func1,func2,func3]  

          print(lst)

       一个函数:  lst[0]()

       那么循环:  for el in lst:   注意:lst内部元素没有类型限制

               el()

          lst=[func1(),func2(),func3()]函数+()就是调用,返回列表是None.

                 (3) 函数名可以像返回值一样返回--------------导致在函数外面访问了函数内部的函数.

        def wrapper():

          def inner():

            print("哈哈")

          return inner

        ret = wrapper()

        ret()  #在函数外面访问了函数内部函数

        ###思考### 与return inner()  有什么区别

                (4)函数可以作为参数进行传递

                          (1) def func1():

          print("谢晋")

        def func2():

          print("杨士奇")

        def func3():

          print("徐渭")

        def proxy(a):##a就是变量,形参

           a()

        proxy(func1)    ##func1函数名作为参数传递

        proxy(func3)

       (2)装饰器的雏形=代理模式

          def proxy(a):##a就是变量,形参

            print("代理开始")

           a()

            print("代理结束完毕")

2.闭包-------->函数的嵌套

      内层函数对外层函数中的变量的使用.

        def wrapper():

          name="周杰伦"

          def inner():

            print(name)   #在内层函数中使用了外层函数的局部变量

           return inner     返回函数名

                           ret=wrapper()

        ret()

     回想全局变量,发现全局变量很不安全,甚至可以修改.

闭包的优点:(1)可以保护变量不被其他人侵害

                   (2) 保持一个变量常驻内存

          def wrapper():

          name="周杰伦"       ###局部变量常驻内存

          def inner():

            print(name)   #在内层函数中使用了外层函数的局部变量

           return inner     返回函数名

                           ret=wrapper()     ###ret是一个内层函数

        ret()   ##ret是inner,执行时间不确定,必须保证里面的name必须存在.

实例  :超级简易版爬虫

 1 from urllib.request import urlopen # 导入一个模块 # 干掉数字签名 
 2 import ssl ssl._create_default_https_context = ssl._create_unverified_context 
 3 
 4 
 5 def func(): # 获取到网页中的内容, 当网速很慢的时候. 反复的去打开这个网站. 很慢 
 6    content = urlopen("https://www.dytt8.net/").read() 
 7     def inner(): 
 8 
 9    return content.decode("gbk") # 网页内容 
10    return inner 
11 
12 
13 print("开始网络请求") r
14 et = func() # 网络请求已经完毕
15 print("网络请求完毕") 
16 print("第一次", ret()[5]) 
17 print("第二次", ret()[5]) # 

如何通过代码查看闭包

     函数.__closure__  来查看,用print(函数.__closure__ ).如果返回内容,则是闭包,如果返回None,则不是闭包.

def wrapper():
    name = "alex"

    def inner():
        print(name)

    print(inner.__closure__)  # 查看是否是闭包. 有内容就是闭包, 没有内容就不是闭包
    inner()


wrapper()

 返回

 

1 C:\Python\Python37\python.exe "F:/python_课程资料/老男孩/day11 第一类对象 闭包 迭代器/code/day11 第一类对象 闭包 迭代器/04 闭包.py"
2 (<cell at 0x0000000001DEC7C8: str object at 0x0000000001DC2F80>,)
3 alex
4 
5 Process finished with exit code 0

如果不是闭包,如下:

 

def wrapper():
    name = "alex"

    def inner():
        print("baozi")

    print(inner.__closure__)  # 查看是否是闭包. 有内容就是闭包, 没有内容就不是闭包
    inner()

返回:

 

C:\Python\Python37\python.exe "F:/python_课程资料/老男孩/day11 第一类对象 闭包 迭代器/code/day11 第一类对象 闭包 迭代器/04 闭包.py"
None
baozi

Process finished with exit code 0

3. 迭代器

    (1)查询某某对象是否是可迭代对象

    iterable 可迭代的

    通过dir() 可以帮助查看某某数据能够执行的操作,其中"__iter__"代表可以迭代.

    经过试验,所有带有"__iter__"可以进行for循环,带有"__iter__"的数据类型就是可迭代对象.

     str ,list,tuple,dict,句柄,range()都是可迭代对象;int,bool不可迭代.

    (2)  lterator -------迭代器

      

 lst = ["贾樟柯", "李安", "杨德昌", "王家卫"]

 print("__iter__" in dir(lst))
 it = lst.__iter__()  # 拿到的是迭代器 <list_iterator object at 0x0000000001DCC160>
print(it.__next__()) # 下一个
print(it.__next__()) # 下一个
print(it.__next__()) # 下一个
print(it.__next__()) # 下一个
print(it.__next__()) # 下一个 # StopIteration 停止迭代

      迭代器特点:

         1.节省内存----生成器

         2.惰性机制

                                3. 只能向下执行,不能反复;

                                                   结束时会扔出一个错误 ------StopIteration

      意义:整合所有的数据类型进行遍历(int,bool除外)

                     如果想重新再迭代,得再获取 迭代器.

        it=lst.__iter__()   ##重新获取迭代器.

      理解::医生叫号模式,不排队的病人.

    

lst = ["海尔兄弟", "阿童木", "葫芦娃", "舒克贝塔", "大风车"]
# 模拟for循环 for el in lst:
it = lst.__iter__() # 获取到迭代器0
while 1: # 循环
    try: # 尝试
        el = it.__next__() # 那数据
        print(el)
    except StopIteration: # 出了错误, 意味着数据拿完了
        break # 结束循环

      lst可是未知量的

4.(1)官方通过代码判断是否是迭代器

  借助于两个两个模块.Iterator 迭代器,Iterable 可迭代的

from collections import Iterable,Iterator

lst=[1,2,3]

print (isinstance(你,树))#判断xxx是不是xx类型,false.

print (isinstance(lst,Iterable))  判断lst是不是可迭代的,True

print (isinstance(lst,Iterator))  判断lst是不是迭代器,false

 

it=lst.__iter__()   

print (isinstance(lst,Iterable))  判断it是不是可迭代的,True

print (isinstance(lst,Iterator))  判断it是不是迭代器,True

   得出结论:

           迭代器一定可迭代,可迭代的东西不一定是迭代器.

for el in it :

     print(el)

    (2)野路子判断是否是迭代器

      用dir()寻找其支持的操作:

                __iter__ 可迭代的

                 __iter__   __next__ 迭代器(找到这两个操作就可以判断为是迭代器)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

    

 

 

 

 

 

 

 

 

 

         

 

        

 

 

 

 

 

 

 

 

         ()

 

 

        

        

 

 

 

 

 

 

 

 

 

 

 

          

posted on 2018-12-11 20:05  赤子之心心有所属  阅读(87)  评论(0编辑  收藏  举报

导航