⼀. 函数名的运⽤. 

1.函数名的内存地址

def func():    
  print("呵呵")
  print(func)

结果: <function func at 0x1101e4ea0>

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

def func():    
    print("呵呵") 
    print(func) 
a = func    # 把函数当成一个变量赋值给另⼀一个变量
a()     # 函数调用 func()

3. 函数名可以当做容器类的元素

def func1():    
    print("呵呵") 
def func2():    
    print("呵呵") 
def func3():    
    print("呵呵") 
def func4():    
    print("呵呵")
lst = [func1, func2, func3]
 for i in lst:    
    i()

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

def func():
    print("吃了了么")
def func2(fn):
    print("我是func2")
    fn()    # 执⾏行行传递过来的fn
    print("我是func2")
func2(func)

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

def func_1():    
    print("这⾥里里是函数1")    
def func_2():        
        print("这⾥里里是函数2")    
    print("这⾥里里是函数1")   
     return func_2 
fn = func_1()   # 执⾏行行函数1.  函数1返回的是函数2, 这时fn指向的就是上⾯面函数2
fn()   

  二. 闭包

什么是闭包?  闭包就是内层函数, 对外层函数(非全局)的变量的引⽤. 叫闭包 

def func1():    
    name = "alex"    
def func2():        
    print(name)     # 闭包    
func2() 
func1() 
结果: alex
 

1.我们可以使⽤用__closure__来检测函数是否是闭包. 使⽤用函数名.__closure__返回cell就是
闭包. 返回None就不是闭包

def func1():    
    name = "alex"    
    def func2():        
        print(name)     # 闭包    
    func2()    
    print(func2.__closure__)    # (<cell at 0x10c2e20a8: str object at 0x10c3fc650>,) 
func1()     

2.如何在函数外边调⽤用内部函数呢? 

def outer():    
    name = "alex"    
    # 内部函数    
    def inner():        
        print(name)    
    return inner
 fn = outer()   # 访问外部函数, 获取到内部函数的函数地址
 fn()    # 访问内部函数    

3.  那如果多层嵌套呢?  很简单, 只需要一层一层的往外层返回就行了.

def func1():    
    def func2():        
        def func3():            
            print("嘿嘿")        
        return func3    
    return func2 
func1()()()            

4.使⽤用闭包, 可以保证外层函数中的变量量在内存中常驻

 1 from urllib.request import urlopen 
 2 def but():    
 3 content = urlopen("http://www.xiaohua100.cn/index.html").read()                                
 4     def get_content():        
 5         return content    
 6     return get_content
 7 fn = but()  
 8 content = fn()  # 获取内容 
 9 print(content) 
10 content2 = fn()  # 重新获取内容
11 print(content2)                                 

综上, 闭包的作⽤用就是让⼀一个变量量能够常驻内存. 供后⾯面的程序使⽤.

三. 迭代器

1. 我们还可以通过isinstence()函数来查看一个对象是不是迭代器。

from collections import Iterable
from collections import Iterator 
print(isinstance(l,Iterable)) #i为对象

2. 使用while循环+迭代器来模拟for循环(必须要掌握)

lst=[1,2,3]
aa=lst.__iter__()
while True:
    try:
        print(aa.__next__()
    except StopIteration:
        break

总结: 

Iterable: 可迭代对象. 内部包含__iter__()函数

 Iterator: 迭代器. 内部包含__iter__() 同时包含__next__(). 

迭代器的特点: 

 1. 节省内存.           

2. 惰性机制           

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

 我们可以把要迭代的内容当成⼦子弹. 然后呢. 获取到迭代器__iter__(), 就把⼦子弹都装在弹夹 中.  然后发射就是__next__()把每⼀一个⼦子弹(元素)打出来. 也就是说, for循环的时候. ⼀一开始的 时候是__iter__()来获取迭代器. 后⾯面每次获取元素都是通过__next__()来完成的. 当程序遇到 StopIteration将结束循环.