python全栈开发 课程 随笔 Day 11
今日主要内容:
1,函数名的运用
2.闭包
3.迭代器
一.函数名的运用
1.函数名的命名规范和变量是一样的
函数名其实就是变量名
(1)函数名的内存地址
例:
def func(): print("alex") print(func) #<function func at 0x0000000002033E18>
(2)函数名可以赋值给其他变量
例:
def func(): print("呵呵") print(func) a = func # 把函数当成一个变量赋值给另一个变量 a() # 函数调用 func()
函数名可以作为参数传递给函数 def my(): print("我是my") def proxy(fn): # 代理模式. 装饰器 print("在处理之前") fn() print("在处理之后") proxy(my) #把函数名作为参数传递给另一个函数
a = 10 b =a(赋值操作) print(b)
(3)函数名可以作为列表的元素进行存储.
例:
def func1(): pass def func2(): pass lst = [func1, func2] for el in lst: el()
(4)函数名可以作为参数传递给函数.
例:
def func(): pass def proxy(fn): fn() proxy(func)
def func1(): print("我是func1") def func2(): print("我是func2") def func(fn, gn): # 函数名可以作为参数进行传递 print("我是func") fn() gn() print("哈哈哈") func(func1, func2)
(5)函数名可以作为函数的返回值
例:
def func(): def inner(): pass return inner func()()
def func(): print("我是func") a = 10 # 变量 def inner(): print("我是inner") return inner # ret = func() #(最后一行的转化过程源头) # ret() #(最后一行的转化过程源头) func()() # 先运行func() 然后在返回值上加()
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 outer(): a = 10 def inner(): print(a) return inner
例:
def func1(): name = "alex" def func2(): print(name) # 闭包 func2() func1() 结果: alex
闭包的作用;
(1) 保护你的变量不受侵害.
例:
a = 10 # 不安全的 def outer(): global a #如果没有global 就无法引用外部变量,保证内部变量不外泄.不被侵犯 a = 20 def outer_2(): global a a = 30 outer_2() outer() print(a)
(2)可以让一个变量常住内存.供后面的程序使用.
例:
def outer(): a = 10 # 常驻内存, 为了inner执行的时候有值. def inner(): print(a) # return inner fn = outer() print("fdsafasd") print("fdsafasd") print("fdsafasd") fn() # 调用的时机是不定的.
简易爬虫实例(邱彦涛(涛哥)珍藏校花美女大全)
例:
# 超简易爬虫 from urllib.request import urlopen def outer(): # 常驻内存 s = urlopen("http://www.xiaohua100.cn/index.html").read() def getContent(): # 闭包 return s return getContent print("爬取内容.....") pa = outer() ret = pa() print(ret) # (过段时间) ret = pa() print(ret) # (又过一段时间调用) ret = pa() print(ret) # (又又过一段时间调用) ret = pa() print(ret) # ...............(此处省去 N + 1 次)
(3)如何查看是否闭包.
方法: 我们可以使用__closure__来检测函数是否是闭包. 使用函数名.__closure__返回cell就是闭包. 返回None就不是闭包.
例:
def func1(): name = "alex" def func2(): print(name) # 闭包 func2() print(func2.__closure__) func1() # (<cell at 0x10c2e20a8: str object at 0x10c3fc650>,)
def func(): a = 10 def inner(): print(a) print(inner.__closure__) # 如果打印的是None. 不是闭包. 如果不是None, 就是闭包 func() #(<cell at 0x00000000026465B8: int object at 0x000000005286B560>,)
三.迭代器.
使用dir来查看该数据包含了那些方法
用来遍历列表,字符串,元祖....可迭代对象
可迭代对象: Iterable, 里面有__iter__()可以获取迭代器, 没有__next__()
迭代器: Iterator, 里面有__iter__()可以获取迭代器, 还有__next__()
数据必须是可迭代的
例:
# 对的 s = "abc" for c in s: print(c) # 错的 for i in 123: print(i) 结果: Traceback (most recent call last): File "/Users/sylar/PycharmProjects/oldboy/iterator.py", line 8, in <module> for i in 123: TypeError: 'int' object is not iterable
迭代数据类型和迭代器
(1)可迭代对象可以使用__iter__()来获取到迭代器
(2)迭代器里面有__next__()
例:
s = '123' for i in s: print(i) print(dir(str)) # dir查看xx类型的数据可以执行哪些方法, __iter__ iterable print(dir(list)) # __iter__ print(dir(int)) # 没有__iter__ # 所有的带__iter__可以使用for循环的, 可迭代对象 结果: 1 2 3 ['__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'] ['__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'] ['__abs__', '__add__', '__and__', '__bool__', '__ceil__', '__class__', '__delattr__', '__dir__', '__divmod__', '__doc__', '__eq__', '__float__', '__floor__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__getnewargs__', '__gt__', '__hash__', '__index__', '__init__', '__init_subclass__', '__int__', '__invert__', '__le__', '__lshift__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__round__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', '__xor__', 'bit_length', 'conjugate', 'denominator', 'from_bytes', 'imag', 'numerator', 'real', 'to_bytes']
查看一个对象是否是可迭代对象的方法:
(偏方)
print("__iter__" in dir(it)) print("__next__" in dir(it)) 可以通过dir来判断数据是否是可迭代的, 以及数据是否是迭代器
(官方方法)
from collections import Iterable # 可迭代对象 from collections import Iterator # 迭代器
迭代器的特点:
1. 只能向前.
2. 几乎不占用内存, 节省内存(需要明天生成器)
3. for循环
4. 惰性机制 (面试题,难度系数比较高)
例:
s = "石可心喜欢赵一宁" it = s.__iter__() # 获取迭代器 print(dir(it)) # 迭代器里有__iter__ 还有__next__ print(it.__next__()) # 石 print(it.__next__()) # 可 print(it.__next__())# 心 print(it.__next__())# 喜 print(it.__next__())#欢 print(it.__next__())#赵 print(it.__next__())# 一 print(it.__next__())# 宁
重点: 迭代器模拟for循环(使用while循环+迭代器来模拟for循环(必须要掌握))
for循环的内部机制.
1. 首先获取到迭代器.
2. 使用while循环获取数据
3. it.__next__()来获取数据
4. 处理异常 try:xxx except StopIteration:
写法:
it = lst.__iter__() # 获取迭代器 while 1: try: # 尝试执行 el = it.__next__() # 获取下一个元素 print(el) except StopIteration: # 处理错误 break ##### ( 重 点 ) #####
1.proxy : 代理 2.stop interation : 停止迭代 3. enfine ; 定义