1. 函数名的应用以及第一类对象
# 函数名是一个变量, 但它是⼀个特殊的变量, 与括号配合可以执⾏函数的变量. # 1. 函数名的内存地址 def func(): print("呵呵") print(func) # <function func at 0x0000022C99B3D1E0> # 2. 函数名可以赋值给其他变量 def func(): print("你吃了吗") print(func) # 打印func的内存地址 a = func # 把函数当成⼀个变量赋值给另⼀个变量 print(a) # 打印a,也是func的内存地址 func() # 函数的调用 a() # 也是函数的调用 # 3. 函数名可以当做容器类的元素 (1) 首先看整数当做列表里的元素: 例: a = 8 b = 7 c = 1 d = 3 lst = [a, b, c, d] print(lst) (2) 再看函数当做列表的元素 def f1(): print("我是马化腾") def f2(): print("我是马云") def f3(): print("我是马赛克") def f4(): print("我是马忠军") 例1: lst = [f1, f2, f3, f4] for el in lst: el() 例2: lst = [f1(), f2(), f3(), f4()] # 这时list是4个None, 因为没有return默认返回None print(lst) # 4. 函数名可以当做函数的参数 例1: def func(fn): fn() def gn(): print("我是火锅, 刚才有人要吃我") func(gn) # 把函数gn当成实参传给func的形参fn 例2: def func(): print("吃了么") def func2(fn): print("我是func2") fn() # 执⾏传递过来的fn print("我是func2") func2(func) # 把函数func当成参数传递给func2的参数fn. # 5. 函数名可以作为函数的返回值 例1: def func(): def inner(): print("火锅不让吃了. 吃了上火") return inner ret = func() # 这里func()执行过后获取到的是inner函数 ret() # 这里是让inner函数执行 例2: def func_1(): print("这⾥是函数1") def func_2(): print("这⾥是函数2") print("这⾥是函数1") return func_2 fn = func_1() # 执⾏函数1. 函数1返回的是函数2, 这时fn指向的就是上⾯函数2 fn() # 执⾏上⾯返回的函数func2
综上: 函数就是一个变量
2. 闭包
# 1. 什么是闭包? 闭包就是内层函数, 对外层函数(非全局)的变量的引⽤. 叫闭包. 例: def func(): name = 'alex' # 常驻内存 防止其他程序改变这个变量 def inner(): print(name) # 在内层函数调用了外层函数的变量,叫闭包. 可以让一个局部变量常驻内存. return inner # 2. __closure__可以来检测函数是否是闭包. 使⽤函数名.__closure__返回cell就 是闭包. 返回None就不是闭包 例: def func1(): name = "alex" def func2(): print(name) # 闭包 print(func2.__closure__) # (<cell at ......>) func2() func1() # 3. 在函数外边调⽤内部函数 (1) 函数里套了一层函数 def outer(): name = "alex" # 内部函数 def inner(): print(name) return inner fn = outer() # 访问外部函数, 获取到内部函数的函数地址 fn() # 访问内部函数 (2) 函数多层嵌套 def func1(): def func2(): def func3(): print("嘿嘿") return func3 return func2 func1()()() 闭包的好处: 1. 常驻内存 2. 防止其他程序改变这个变量
3. 迭代器
# 1. 可迭代的 # 对的 s = "abc" for c in s: print(c) # 错的 for i in 123: print(i) # TypeError: 'int' object is not iterable.(这里iterable表⽰可迭代的. 表⽰可迭代协议.)
# 2. 可迭代(Iterable)对象: str, list, tuple, dict, set, f ,range. # 所有的以上数据类型中都有一个函数__iter__(), 所有包含了__iter__()的数据 类型都是可迭代的数据类型(Iterable) # dir()来查看一个对象,数据类型中包含了那些东西. # 验证数据类型是否符合可迭代协议. 可以通过dir函数来查看类中定义好的所有⽅法. s = "我的哈哈哈" print(dir(s)) # 可以打印对象中的⽅法和函数 print(dir(str)) # 也可以打印类(str类)中声明的⽅法和函数 他们都有__iter__函数, 是可迭代的(Iterable) lst = [1, 2, 3] # list print(dir(lst)) # 其中有__iter__函数,是可迭代对象. s = "王尼玛" # __iter_这个函数是否在他们的的方法中. print("__iter__" in dir(s)) # Ture print("__iter__" in dir(lst)) # Ture print("__iter__" in dir(123)) # False
# 3. 迭代器 # 迭代器从可迭代对象中开始迭代 lst = ["皇阿玛", "皇额娘", "容嬷嬷", "紫薇"] it = lst.__iter__() # 获取迭代器 # 迭代器往外拿元素.__next__() print(it.__next__()) # 皇阿玛 print(it.__next__()) # 皇额娘 print(it.__next__()) # 容嬷嬷 print(it.__next__()) # 紫薇 print(it.__next__()) # 迭代到最后一个元素之后. 再迭代就报错了 # 模拟for循环 lst = ["皇阿玛", "皇额娘", "容嬷嬷", "紫薇"] it = lst.__iter__() # 这个对象获取他的迭代器 while 1: try: name = it.__next__() print(name) except StopIteration: # 拿完了 break
# 3. 迭代器 # 迭代器从可迭代对象中开始迭代 lst = ["皇阿玛", "皇额娘", "容嬷嬷", "紫薇"] it = lst.__iter__() # 获取迭代器 # 迭代器往外拿元素.__next__() print(it.__next__()) # 皇阿玛 print(it.__next__()) # 皇额娘 print(it.__next__()) # 容嬷嬷 print(it.__next__()) # 紫薇 print(it.__next__()) # 迭代到最后一个元素之后. 再迭代就报错了 # 模拟for循环 lst = ["皇阿玛", "皇额娘", "容嬷嬷", "紫薇"] it = lst.__iter__() # 这个对象获取他的迭代器 while 1: try: name = it.__next__() print(name) except StopIteration: # 拿完了 break
# 4. isinstance(对象, 类型) 判断xx对象是否是xxx类型 # 用 Iterable中isinstance方法判断一个对象是否可以迭代时,要先导入包 from collections.abc import Iterator # 迭代器 from collections.abc import Iterable # 可迭代的 lst = [1, 2, 3] # 判断列表是否是可迭代的,是否是迭代器 print(isinstance(lst, Iterable)) # Ture print(isinstance(lst, Iterator)) # False # 判断迭代器是否是可迭代的,是是否是迭代器 it = lst.__iter__() print(isinstance(it, Iterable)) # True 判断是否是可迭代的 迭代器一定是可迭代的 print(isinstance(it, Iterator)) # True 迭代器里面一定有__next__(), __iter__() # 用__iter__, __next__ 判断是否可迭代,是否为迭代器 print("__iter__" in dir(lst)) # True (确定是一个可迭代的) print("__next__" in dir(lst)) # False (确定不是一个迭代器)
# 5. f(文件句柄)是迭代器 # 用isinstance之前先导入包 from collections.abc import Iterator from collections.abc import Iterable # 文件句柄是一个迭代器 f = open("01 课程大纲", mode="r", encoding="utf-8") print(isinstance(f, Iterable)) # Ture print(isinstance(f, Iterator)) # Ture
总结: 可迭代对象(Iterale): str, list, tuple, set, dict 迭代器(Iterator): f, range 可迭代对象(Iterale): 内部包含__iter__(). 迭代器(Iterator): 内部含有__iter__(), __next__()
注意: 可迭代的不一定是迭代器, 但迭代器一定是可以迭代的. 迭代器的特点: 1. 省内存 2. 惰性机制 3. 不能反复, 只能向下执⾏.