函数名的本质与一级对象:
1.函数名表示函数的内存地址。
2.函数名可以赋值给变量,可以作为容器数据类型的元素。
3.函数名可以作为参数传递给函数。
4.函数名可以作为函数的返回值。
#一。 函数名表示函数的内存地址
def func():
    print(111)
print(func)     
>>><function func at 0x00000199DFD22F28>
#二。函数名可以赋值给变量,可以作为容器数据类型的元素。
def func():
    print(111)
f = func      #2.函数名可以赋值给一个变量
f()
>>>
111
def foo1():
    print(1)
def foo2():
    print(2)
def foo3():
    print(3)
def foo4():
    print(4)
l1 = [foo1,foo2,foo3,foo4] #3.函数名可以当做容器类数据类型的元素
for i in l1:
    i()
>>>
1
2
3
4
#三。函数名可以作为参数传递给函数
def fun1():
    print(222)
def func2(x):
    x()
func2(fun1)
>>>
222
#四。函数名可以作为函数的返回值
def func1(x):
    return x       
def func2():
    print(‘in the func2‘)
res = func1(func2)
res()
闭包:
内部函数对外部作用域(非全局作用域)的变量的引用,并返回。该内部函数称为闭包函数。
#这是闭包
def wrapper(x):
    def inner():
        print(x)
    inner()
wrapper(‘he‘)
>>>
‘he‘
#这是闭包
name = ‘he‘
def wrapper(n):     
    def inner():
        print(n)
    return inner()
wrapper(name)
##这不是闭包
name = ‘he‘
def wrapper():
    def inner():
        print(name)     #因为引用了全局作用域的变量
    return inner()
wrapper()
判断一个内部函数是不是闭包有一个好方法:"__closure__"
(1)如果__closure__有cell为闭包函数
(2)如果__closure__返回的是None,则不是闭包函数。
# 这是闭包,返回有cell就是闭包
def func():
    name = ‘he‘
    def inner():
        print(name)
    print(inner.__closure__)
    inner()
func()
>>>
(<cell at 0x00000183451865E8: str object at 0x0000018345217810>,)
he
#这不是闭包,因为返回的是None
name = ‘he‘
def wrapper():
    def inner():
        print(name)
    print(inner.__closure__)
    inner()
wrapper()
>>>
None
he
闭包的作用:
# 回顾前面的知识,python解释器遇到一个函数的执行就会开辟一块新的内存空间,然后随着函数的执行结束,这块内存空间会被释放掉。但是如果一个函数被多次调用,就得多次创建内存,然后释放,再创建,再释放。。。这样对内存的损害很大
# 但是,python解释器有一个机制,一旦检测到你的内层是一个闭包,它会在内存中开辟一块新的空间,这个空间不会随着函数的结束而释放。起到了保护内存的作用。
闭包的嵌套:
‘‘‘闭包嵌套‘‘‘
def wrapper():
    money = 1000
    def func():
        name = ‘he‘
        def inner():
            print(name + ‘ have ‘ + str(money))
        return inner
    return func
f = wrapper()
i = f()
i()
可迭代对象(iterable)与可迭代器(iterator)
一. 可迭代对象
前提:在python中,可以理解成一切皆对象。
可迭代对象:(1)对象内部含有"__iter__"方法,就是可迭代对象。
(2)可迭代对象满足可迭代协议。
#回顾我们学过的可迭代对象:str,list,tuple,dict,set,range() # dir(obj) 方法:返回一个对象的所有方法 s1 = ‘str‘ print(dir(s1)) #返回了字符串的所有方法 >>> [‘__add__‘, ‘__class__‘, ‘__contains__‘, ‘__delattr__‘, ‘__dir__‘, ‘__doc__‘, ‘__eq__‘, ‘__format__‘, ‘__ge__‘, ‘__getattribute__‘, ‘__getitem__‘, ‘__getnewargs__‘, ‘__gt__‘, ‘__hash__‘, ‘__init__‘, ‘__init_subclass__‘, ‘__iter__‘, ‘__le__‘, ‘__len__‘, ‘__lt__‘, ‘__mod__‘, ‘__mul__‘, ‘__ne__‘, ‘__new__‘, ‘__reduce__‘, ‘__reduce_ex__‘, ‘__repr__‘, ‘__rmod__‘, ‘__rmul__‘, ‘__setattr__‘, ‘__sizeof__‘, ‘__str__‘, ‘__subclasshook__‘, ‘capitalize‘, ‘casefold‘, ‘center‘, ‘count‘, ‘encode‘, ‘endswith‘, ‘expandtabs‘, ‘find‘, ‘format‘, ‘format_map‘, ‘index‘, ‘isalnum‘, ‘isalpha‘, ‘isdecimal‘, ‘isdigit‘, ‘isidentifier‘, ‘islower‘, ‘isnumeric‘, ‘isprintable‘, ‘isspace‘, ‘istitle‘, ‘isupper‘, ‘join‘, ‘ljust‘, ‘lower‘, ‘lstrip‘, ‘maketrans‘, ‘partition‘, ‘replace‘, ‘rfind‘, ‘rindex‘, ‘rjust‘, ‘rpartition‘, ‘rsplit‘, ‘rstrip‘, ‘split‘, ‘splitlines‘, ‘startswith‘, ‘strip‘, ‘swapcase‘, ‘title‘, ‘translate‘, ‘upper‘, ‘zfill‘]
怎么判断一个对象是否为可迭代对象:
(1)判断方法"__iter__"是否在对象的方法中,因可迭代对象都含有‘__iter__‘
(2)通过isinstance(obj,type)来判读,返回True/False
from collection import Iterable
isinstance(obj,Iterabel)
# 方法一:通过对象是否含有‘__iter__’方法
dic = {‘name‘:‘he‘,‘age‘:23}
print(‘__iter__‘ in dir(dic))
>>>
True
# 方法二:通过isinstance()方法判断
from collections import Iterable
dic = {‘name‘:‘he‘,‘age‘:23}
print(isinstance(dic,Iterable))
>>>
True
二.迭代器(Iterator)
迭代器:对象内部既含有"__iter__"又含有"__next__"方法的就是迭代器。
判断一个对象是否为迭代器:
(1)这个对象的方法中是否含有‘__iter__‘和‘__next__‘
(2)通过isinstace(obj,type)来判断
#我们接触过得迭代器有:文件句柄 # 方法一:判断对象的方法中是否同时含有"__iter__"和"__next__" f = open(r‘E:\python_training_s1\day9\register.txt‘,encoding=‘utf-8‘) print(‘__iter__‘ in dir(f)) print(‘__next__‘ in dir(f)) f.close() >>> True True #方法二:使用isinstance(obj,Iterator),返回True/False from collections import Iterator f = open(r‘E:\python_training_s1\day9\register.txt‘,encoding=‘utf-8‘) print(isinstance(f,Iterator)) f.close() >>> True
三.可迭代对象VS迭代器
(1)可迭代对象与迭代器有什么不同?
1.可迭代对象不能取值(之所以能取,是python中作了优化),迭代器能够取值。
2.迭代器非常节省内存,每次只会取一个值,在内存中只占一个内存空间。
3.迭代器是单向的,不能够反复。
(2)可迭代对象转换成迭代器,iterable.__iter__()
l1 = [1,2,3] #可迭代对象 iter_l1 = l1.__iter__() #迭代器 iter(iterable_obj) print(iter_l1,type(iter_l1)) print(iter_l1.__next__()) print(iter_l1.__next__()) print(iter_l1.__next__())
(3)for循环的内部原理
1.将可迭代对象转换为迭代器。
2.调用__next__方法取值
3.利用异常处理停止报错
# 使用while循环重现for循环的原理
s1 = ‘abcd‘
iter1 = s1.__iter__()
while 1:
    try:
        print(iter1.__next__())
    except Exception:
        break
原文:https://www.cnblogs.com/hebbhao/p/9493634.html