zoukankan      html  css  js  c++  java
  • 第十二天-函数名 迭代器

    # 函数名的应用:
    # 函数名命名与变量相同
    # 函数名就是变量名,一个特殊的变量,与括号配合可以执行函数的变量,函数名存储的是函数的内存地址


    # 函数名的内存地址
    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("
    结束了")
    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. 不能反复,只能向下执行.




  • 相关阅读:
    jstl插件使用
    IDEA配置tomcat
    Spring框架
    2020/7/17 JAVA模拟斗地主发牌洗牌
    2020/7/15 JAVA之Map接口
    2020/7/14 Java之增强for循环、泛型、List接口、Set接口
    2020/7/13 集合之ArrayList集合、Collection接口、Iterator迭代器
    2020/7/13 常用API之基本类型包装类、System类、Math类、Arrays类、大数据运算
    2020/7/11 日期相关类
    2020/7/8 JAVA总结之:匿名对象/内部类/包的声明与访问/访问修饰符/代码块
  • 原文地址:https://www.cnblogs.com/xi1419/p/9885671.html
Copyright © 2011-2022 走看看