第十二天-函数名 迭代器
程序员文章站
2022-06-30 12:18:39
# 函数名的应用:# 函数名命名与变量相同# 函数名就是变量名,一个特殊的变量,与括号配合可以执行函数的变量,函数名存储的是函数的内存地址 # 函数名的内存地址 1 def func(): 2 print("哈哈") 3 4 print(func) # 打印结果: 5 # 直接使用函数名得到的是函数... ......
# 函数名的应用:
# 函数名命名与变量相同
# 函数名就是变量名,一个特殊的变量,与括号配合可以执行函数的变量,函数名存储的是函数的内存地址
# 函数名的内存地址
1 def func(): 2 print("哈哈") 3 4 print(func) # 打印结果:<function func at 0x000002ba13c199d8> 5 # 直接使用函数名得到的是函数名的内存地址
# 函数名可赋值给变量
1 def func(): 2 print("呵呵") 3 4 a = func # 把函数当一个变量赋值给另一个变量 5 a() # 加()调用函数 func() 打印结果: 呵呵 6 7 # 变量代理模式(装饰器的雏形) 8 def chi(fn): # fn 代理he func1 func2 dnf 9 print("开挂") 10 fn() 11 print(fn.__name__) 12 print("洗包") 13 14 def dnf(): 15 print("疯狂的刷") 16 17 def func1(): 18 print("我是func1") 19 20 def func2(): 21 print("我是func2") 22 23 def he(): 24 print("我要喝酒") 25 26 chi(he) 27 # chi(dnf) 28 # chi(func1)
# 函数名可当容器类元素
1 def func1(): 2 print("哈哈") 3 4 def func2(): 5 print("呵呵") 6 7 def func3(): 8 print("吼吼") 9 10 lis = [func1,func2,func3] # 作为列表元素 11 # print(lis) # 函数内存地址 12 for i in lis: 13 i() # 哈哈 呵呵 吼吼 14 # str, list, tuple, dict, set 也可
# 函数名可作为函数的参数
1 def func(): 2 print("还好吧") 3 4 def func1(fun): 5 print("还好吗") 6 fun() # 加()执行传递过来的fun(即函数func()) 7 # print(fun) # 不加是函数名内存地址 8 print("不太好") 9 10 func1(func) # 把函数func作为func1的参数 11 ''' 12 还好吗 13 还好吧 14 不太好 15 '''
# 函数名作为函数的返回值
1 def func1(): 2 print("这里是函数1") 3 def func2(): 4 print("这里是函数2") 5 print("这里是函数1") 6 return func2 7 8 fn = func1() # 执行函数1 返回值是func2 9 fn() # 加()执行函数2 10 func1()() # 等同于上面
# 闭包
# 内层函数对外层函数变量(非全局)的调用,叫作闭包
1 # 例子 2 a = 10 3 def func1(): 4 print(a) 5 6 def func2(): 7 print(a) 8 9 func1() # 这里没问题 都能输出 a = 10 10 func2() 11 12 13 # 假如你同事搞事情 14 def func3(): 15 global a 16 a = 20 17 18 func3() # global 改变了全局变量 你的变量a会被改变 19 func2() # 变成了 20 20 21 # 由上可知 # 全局的东西是不安全的
# 安全使用变量
1 def func(): 2 a = 10 # 安全的 3 def func2(): 4 print(a) # 闭包 5 def func3(): 6 print(a) # 闭包 7 func3() 8 return func2 9 10 # def func4(): # 除非你自己内部作死 11 # nonlocal a 12 # a = 20 13 14 print(func()()) # 结果仍然为10 安全的 函数外部无法改变
# 由上可知:
# 闭包: 内层函数对外层函数的变量的使用
# 作用:
# 1. 保护我们的变量不受损害
# 2. 可以让一个变量常驻内存.
1 # 为何变量不受损害 2 def outer(): 3 a =10 4 def inner(): 5 print("嘿嘿") 6 print(a) 7 return inner 8 9 set = outer() 10 # 如果这里 再执行n行代码... 11 # set() inner是不确定什么时候执行的 必须要保证innter可以正常执行.必须把a保留到最后
# 函数外部调用函数内部函数
1 def outer(): 2 name = "王尼玛" 3 def inner(): 4 print(name) 5 return inner 6 7 fn = outer() # 返回inner 得到内部函数的内存地址 8 fn() # 访问到内部函数 9 outer()() # 也可以这样写 10 11 # 如果是多层 一层一层往外套就行 12 def func1(): 13 def func2(): 14 def func3(): 15 print("哈哈") 16 return func3 17 return func2 18 19 func1()()()
# 使用_closure_检测闭包
# 返回cell是闭包,none不是 变量名.__closure__
1 def func(): 2 name = "王尼玛" 3 def func1(): 4 print(name) # 闭包 5 # print("龙傲天") # 没闭包 6 func1() 7 print(func1.__closure__) # (<cell at 0x000001ebc477f6d8: str object at 0x000001ebc4782150>,) 8 9 # func() # 返回是 cell 闭包
# 闭包让变量常驻内存,供后续使用
1 # 例子-low版爬虫 2 from urllib.request import urlopen # 打开一个连接用的模块 3 # 外层函数 4 def but(): 5 # 打开连接. 读取源代码 6 content = urlopen("http://www.cctv.com/").read() # 永久驻留在内存 7 # 内层函数 8 def get_content(): 9 return content # 返回content 直接调用 10 return get_content # 内层函数 11 12 fn = but() # 这里会很慢. 需要网络请求 13 print(fn()) # 不会再进行网络请求了 14 print(fn())
# 关联小知识点
# 函数注释 关键点 复杂点 一定要写注释
1 def func(a,b): 2 ''' 3 文档注释 4 这个函数用来计算两个数的和并返回 5 :param a: 第一个数 6 :param b: 第二个数 7 :return: 第一个数和第二个数的和 8 autho:王尼玛 9 date:2018-10-31 10 ''' 11 print("我是func") 12 return a+b 13 14 print(func.__doc__) # 获取函数注释 15 16 print(func.__name__) # 获取函数名 多用在函数名很多调用不清时(如:装饰器等)
# 迭代器:
# str, list, tuple, dict, set 我们称之为可迭代对象,因为他们都遵循了可迭代协议
# 什么是可迭代协议
1 s = "abcde" 2 for c in s: 3 print(c) # 能正常迭代输出 4 5 i = 123 6 for c in i: 7 print(c) # 报错 8 # 结果 typeerror: 'int' object is not iterable 9 # iterable 表示可迭代的 表示可迭代协议
# 使用dir函数检测是否迭代
1 s = "哈哈哈啊哈" 2 print(dir(s)) # 查看对象中的方法和函数 3 print(dir(str)) # 打印类中声明的方法和函数 发现 __iter__ 字符串可被迭代 4 # 字符串中可以找到__iter__.
# 继续看list,dict,tuple,range,open,set
1 print(dir(list)) 2 print(dir(dict)) 3 print(dir(tuple)) 4 print(dir(range)) 5 print(dir(open("王尼玛.txt",mode="w"))) 6 print(dir(set)) 7 8 # 可得出 都有 __iter__ 同时都是可进行for循环 9 # 综上.可确定对象中有 __iter__ 函数. 那么这个对象可迭代的数据类型,可以获取到相应的迭代器 10 # 这里的__iter__是获取到对象的迭代器.可用迭代器中的__next__()来获取到一个迭代器中的元素.
# 可迭代的 iterable 迭代器 iterator
1 lis = ["秦皇","汉武","唐宗","宋祖"] 2 it = lis.__iter__() 3 print(it) # <list_iterator object at 0x00000197f6fd4240> # iterator迭代器 4 print(dir(it)) # 迭代器本身是可迭代的 5 # 6 # # 拿到迭代器后,可用__next__()获取数据 7 print(it.__next__()) # 秦皇 8 print(it.__next__()) # 汉武 9 print(it.__next__()) # 唐宗 10 print(it.__next__()) # 宋祖 11 print(it.__next__()) # stopiteration 迭代器中没有元素了 报错 停止迭代 12 13 # 用循环来进行上面的代码: 14 it = lis.__iter__() # 重新获取迭代器 15 while 1: 16 # it = lis.__iter__() # 不可放这,会永远拿第一个死循环下去 17 el = it.__next__() 18 print(el) # 执行循环结束出现如上报错 stopiteration 19 # 优化 20 it = lis.__iter__() # 重新获取迭代器 21 while 1: 22 try: 23 el = it.__next__() 24 print(el) # 循环完,不报错。 25 except stopiteration: 26 print("\n结束了") 27 break 28 29 # 以上即是for循环的流程(用while表达出来) 30 # for循环的流程: 31 # it = lst.__iter__() 32 # while 1: 33 # try: 34 # el = it.__next__() 35 # for循环的循环体 36 # except stopiteration: 37 # break
# 迭代器三个特点:
# 节省内存(生成器)
# 惰性机制,必须用__next__()来获取数据
# 只能往前,不能后退
1 # 迭代器回头的方法: 2 it = lis.__iter__() 3 print(it.__next__()) # 秦皇 4 print(it.__next__()) 5 print(it.__next__()) 6 print("回去") 7 it = lis.__iter__() # 重新获取新迭代器(可理解成一次性用品) 8 print(it.__next__()) # 秦皇 重新获取后又重头开始 9 print(it.__next__()) 10 print(it.__next__())
# 判断一个对象是否可迭代对象
# 1.dir() -> __iter__ 可迭代的
# dir() -> __next__ 迭代器
1 lst = ["秦始皇", "汉武帝", "孝文帝", "隋炀帝", "李世民"] 2 print("__iter__" in dir(lst)) # true 可迭代的 3 print("__next__" in dir(lst)) # false 不是迭代器 4 5 print("__iter__" in dir(int)) # false 6 print("__next__" in dir(int)) # false 7 8 it = lst.__iter__() # 迭代器 9 print("__iter__" in dir(it)) # true 迭代器本身就是可迭代的 10 print("__next__" in dir(it)) # true 是迭代器
# 2 官方方法
# collections 关于集合类的相关擦操作
# iterable 可迭代的
# iterator 迭代器
1 # collections 关于集合类的相关擦操作 2 # iterable 可迭代的 3 # iterator 迭代器 4 lst = ["秦始皇", "汉武帝", "孝文帝", "隋炀帝", "李世民"] 5 from collections import iterable, iterator 6 print(isinstance(lst , iterable)) # true 是可迭代的 7 print(isinstance(lst, iterator)) # false 不是迭代器 8 9 # 判断集合 10 print(isinstance({1,2,3}, iterable)) # true 可迭代 可用for
# 总结:
# iterable: 可迭代对象. 内部包含__iter__()函数
# iterator: 迭代器. 内部包含__iter__() 同时包含__next__().
# 迭代器的特点:
# 1. 节省内存.
# 2. 惰性机制
# 3. 不能反复,只能向下执行.
下一篇: PHP四种排序方式和二分查找。
推荐阅读
-
【第十四篇】Python 迭代器
-
python基础(13):函数名的使用、第一类对象、闭包、迭代器
-
java基础第十二篇之集合、增强for循环、迭代器和泛型
-
11.Python初窥门径(函数名,可迭代对象,迭代器)
-
python迭代器(函数名的应用,新版格式化输出f)
-
第十二天-函数名 迭代器
-
学习python的第十六天(迭代器,三元表达式,列表生成式,字典生成式,生成器,递归(没深入理解)
-
学习11:总结# 1.函数名第一类对象及使用 ***** # 2.f格式化 *** # 3.迭代器 **** # 4.递归 ****
-
Python函数名应用/闭包/迭代器/
-
学习11:内容# 1.函数名第一类对象及使用 ***** # 2.f格式化 *** # 3.迭代器 **** # 4.递归 ****