一. 函数名的运用.
函数名是⼀个变量, 但它是⼀个特殊的变量, 与括号配合可以执行函数的变量.
1. 函数名的内存地址
def func(): print("今天下大雨啦") print(func) <function func at 0x0000014AA40DD1E0>
2. 函数名可以赋值给其他变量
def func(): print("今天下大雨") a=func # 函数名就是一个变量
print(a) #<=>print(func)
a() #<=>func() # 就是一个函数的调用
<function func at 0x000002A8CB3DD1E0>
今天下大雨
3. 函数名可以当做容器类的元素
a=1 b=2 c=3 d=4 lst=[a,b,c,d] print(lst) [1, 2, 3, 4]
def func1(): print("今天下雨了") def func2(): print("昨天下雨了") def func3(): print("前天也下雨了") lst=[func1,func2,func3] print(lst) [<function func1 at 0x000001ED1902D1E0>, <function func2 at 0x000001ED191D7D90>, <function func3 at 0x000001ED191D7E18>]
def func1(): print("今天下雨了") def func2(): print("昨天下雨了") def func3(): print("前天也下雨了") lst=[func1(),func2(),func3()] print(lst) 今天下雨了 昨天下雨了 前天也下雨了 [None, None, None]
4. 函数名可以当做函数的参数
def func(food): print("吃",food) a="炒饼" func(a) 吃 炒饼
def func(): print("吃了么") def func2(fn): print("我是func2") fn() # 执行传递过来的fn print("我是func2") func2(func) # 可以把函数作为参数, 传递给另一个函数
我是func2 吃了么 我是func2
5. 函数名可以作为函数的返回值
def func(): def inner(): print("下大雨") return inner ret = func() # 这里func()执行之后获取到的是inner函数 ret() 下大雨
综上. 函数就是一个变量
二. 闭包
闭包就是内层函数, 对外层函数(非全局)的变量的引用叫闭包
def func(): name="dema" # 常驻内存 防止其他程序改变这个变量 def inner(): print("name") # 在内层函数中调用了外层函数的变量,叫闭包, 可以让一个局部变量常驻内存 inner() func()
爬虫代码 from urllib.request import urlopen def but(): content = urlopen("http://www.xiaohua100.cn/index.html").read() def inner(): return content # 在函数内部使用了外部的变量 . 闭包 print(inner.__closure__) # 查看inner是否是闭包, 如果有东西就是闭包, 没东西就不是闭包 return inner fn = but() # 这个时候就开始加载校花100 的内容 # 后⾯需要⽤到这⾥⾯的内容就不需要在执⾏⾮常耗时的⽹络连接操作了 content = fn() # 获取内容 print(content) content2 = fn() # 重新获取内容 print(content2)
综上, 闭包的作用就是让一个变量能够常驻内存. 供后面的程序使⽤.
三. 迭代器
s="今天雨下的很大" for i in s: print(i) 对的 for c in 123: print(c) 错误:'int' object is not iterable
可迭代对象: str, list, tuple, set, f, dict
所有的以上数据类型中都有一个函数__iter__(), 所有包含了__iter__()的数据类型都是可迭代的数据类型 Iterable
s="德玛西亚" print(dir(s)) ['__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', 'isascii', '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']
lst = [1,2,3] print(dir(lst)) ['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__',
'__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__',
'__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__',
'__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
综上:我们发现在字符串中可以找到 __iter__.
dir()来查看一个对象,数据类型中包含了哪些东西
s="无双剑姬" print("__iter__"in dir(s)) True lst=[1,2,3] print("__iter__"in dir(lst)) True s=123 print("__iter__"in dir(s)) False
list是一个Iterable.可迭代的
# lst=["张无忌","谢逊","周芷若","赵敏","大秧歌"] # 获取迭代器 # it = lst.__iter__() # # 迭代器往外拿元素. __next__() # print(it.__next__()) #张无忌 # print(it.__next__()) #谢逊 # print(it.__next__()) #周芷若 # print(it.__next__()) #赵敏 # print(it.__next__() #大秧歌 # print(it.__next__()) # 迭代到最后一个元素之后. 再进行迭代就报错了
lst=["张无忌","谢逊","周芷若","赵敏","大秧歌"] it=lst.__iter__() while True: try: name=it.__next__() print(name) except StopIteration: break 张无忌 谢逊 周芷若 赵敏 大秧歌
from collections import Iterable # 可迭代的
from collections import Iterator # 迭代器
lst = [1, 2, 3] from collections import Iterable from collections import Iterator # isinstence(对象, 类型) 判断xx对象是否是xxx类型的 print(isinstance(lst, Iterable)) True print(isinstance(lst, Iterator)) False
lst = [1, 2, 3] from collections import Iterable from collections import Iterator it = lst.__iter__() print(isinstance(it, Iterable)) # 判断是否是可迭代的 迭代器一定是可迭代的 print(isinstance(it, Iterator)) # 迭代器里面一定有__next__(), __iter__() True True
综上. 我们可以确定. 如果对象中有__iter__函数. 那么我们认为这个对象遵守了可迭代协议. 就可以获取到相应的迭代器. 这里的__iter__是帮助我们获取到对象的迭代器. 我们使用迭代器中的__next__()来获取到一个迭代器中的元素.
print("__iter__" in dir(lst)) # 确定是一个可迭代的
print("__next__" in dir(lst)) # 确定不是一个迭代器
from collections import Iterable from collections import Iterator f = open("lol",mode="r", encoding="utf-8") print(isinstance(f, Iterable)) print(isinstance(f, Iterator)) True True
# 迭代器的特点:
# 1. 节省内存
# 2. 惰性机制
# 3. 只能往前拿. 不能反着拿