20180717 (函数名的应用,闭包,迭代器)

一.函数名的应用,第一类对象

函数名是一个变量,但是他是一个特殊的变量,与括号配合可以执行函数的变量

1.函数名的内存地址

例如:

  def func():

    print("呵呵")

  print(func)              ======>     <function func at 0x00000000027EF7B8>   内存地址

例如:

  def func():

    print("呵呵")

  print(func())        ========> 呵呵   None     没有return  所以返回None

2.函数名可以赋值给其它变量

例如:

  def func():

    print("呵呵")

  print(func)

  a = func                #把函数当成一个变量赋值给另一个变量a

  a()                     #函数调用  func()                       =======>内存地址   和   "呵呵"

3.函数名可以作为list元素

例如:

  def func1():

    print("呵呵")

  def func2():

    print("哈哈")

  def func3():

    print("嘿嘿")

  lst = [func1,func2,func3]             ======>列表里存的是内存地址

  for i in lst:

    i()                       =========>"呵呵","哈哈","嘿嘿"

4.函数名可以当做函数的参数

例如:

  def func(fn):

    fn()

  def gn():

    print("aa")

  func(gn)                   ========>"aa"               #可以把函数作为参数,传递给另一个函数

5.函数名可以作为函数的返回值

例如:         #执行函数1,函数1返回的是函数2,这时func指向的就是上面函数2

  def func():

    print("这里是函数1")

    def inner():

      print("这里是函数2")

    print("这里是函数1")

    return inner

  ret = func()                      #这里func()执行后获取到的是inner函数

  ret()       =============> "aa" "aa" "AA"

二.闭包

闭包就是内层函数,对外层函数(非全局)的变量的引用

例如:

  def func():

    name = "alex"

    def inner():

      print(name)      

    return inner

  ret = func()

  ret()               ===============>alex

闭包两个作用:

(1)可以让一个局部变量常驻内存

(2)防止其他程序改变这个变量  (安全性高)         (变量直接写在全局是不安全的)

判断是不是闭包:   (__closure__)      (如果有东西就是闭包,如果返回None就不是闭包)

例如:

  def func():

    name = "alex"

    def inner():

      print(name)             ======>调用的外层的name="alex"

    inner()

    print(inner.__closure__)

  func()                         ========>返回的是内存地址

例如:爬虫代码

  from urllib.request import urlopen

  def but():

    content = urlopen("网址").read()

    def get_content():

      return content

    return get_content

  fn = but()                                #这个时候就开始加载网址里面的内容了

  content = fn()                       #从这开始从后面开始需要用到这个网址的内容的时候就不需要在执行非常耗时的网络连接操作了                     #从这里获取内容

  print(content)

  content2 = fn()                     #重新获取内容

  print(content2)

三.迭代器

srt   list   dict   tuple   set   文件句柄  f  range()   都是可迭代对象    他们其中都包含了__iter__()  函数   他们都可以进行for循环

dir()    可以查看一个对象数据类型中包含了哪些东西

所有包含了一个函数__iter__()的数据类型都是可迭代的数据类型  Iterable

例如:

  s = "abc"

  print("__iter__" in dir(s))            =====>True    str中包含了__iter__    所以str就是可迭代对象

  for c in s:

    print(c)    ======>  a  b  c   循环遍历

例如:  (list是一个Iterable   可迭代的)

  lst = ["ABC","DEF","123","45"]

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

  #迭代器往外拿元素    .__next__()

  print(it.__next__())            ===>ABC

  print(it.__next__())            ===>DEF

  print(it.__next__())            ===>123

  print(it.__next__())            ===>45

  迭代到最后一个元素后,在进行迭代就报错了

例如:模拟for循环

  lst = ["ABC","DEF","123",45]

  it = lst.__iter__()

  while True:

    try:                         try 和 except StopIteration  是固定搭配

      name = it.__next__()

      print(name)

    except StopIteration:

      break

例如:确定是不是可迭代对象     迭代器

  lst = [1,2,3]

  print("__iter__"  in  dir(lst))         确定是一个可迭代的

  print("__next__"  in  dir(lst))       确定是不是一个迭代器

例如:

  lst = [1,2,3]

  form collections import Iterable                             #可迭代的(Iterable)

  form collections import Iterator                             #迭代器(Iterator)

  print(isinstance(lst.Iterable))                ====>True

  print(isinstance(lst.Iterator))                ====>False

isinstance   判断xx对象是不是xxx对象

例如:

  lst = [1,2,3]

  it = lst.__iter__()

  print(isinstance(it.Iterable))               =====>True

  print(isinstance(it.Iterator))               ======>True

迭代器一定是可迭代的

迭代器里面一定有 .__next__()       .__iter__()

文件句柄  f   是迭代器   

例如:

  f = open("文件名",mode="r",encoding="utf-8")

  print(isinstance(f.Iterable))              ====>True

  print(isinatance(f.Iterator))              ====>True

迭代器的特点:  (1)节省空间   (2)惰性机制   (3)不能反复,只能向下执行(只能往下拿,不能反着拿)

原文地址:https://www.cnblogs.com/lhy979/p/9325567.html