day011 迭代器闭包

三.今日主要内容
1.第一类对象,函数名的使用
函数名就是变量名,函数名存储的是函数的内存地址

变量的命名规范:
1.有数字,字母,下划线组成
2.不能是数字开头,更不能是纯数字
3.不能用关键字
4.不能太长
5.要有意义
6.不要用中文
7.要区分大小写
8.驼峰或者下划线法

2.闭包
闭包:在内层函数中引入外层函数的变量
作用:
1.保护变量不受侵害(javascript)
2.让一个变量常驻内存(函数的调用有可能在很多行代码之后)

3.迭代器
dir() 查看变量能够执行的方法(函数)
Iterable:可迭代的, __iter__()
Iterator:迭代器 __iter__(), __next__()

for循环的过程:
it = lst.__iter__()
while 1:
try:
el = it.__next__()
print(el)
exception StopIteration:
break
从迭代器中获取数据的唯一方法:__next__()

迭代器的三个特性:
1.节省内存空间
2.惰性机制
3.只能往前,不能后退


# 函数名遵循变量名的命名规则

# # 2.函数名的运用
# 1.函数名的内存地址

a = 10
b = a
print(b)

def a():
print("我是可怜的a")

b = a
print(b) #<function a at 0x000002635AF41EA0>, 函数名存储函数命名空间的内存地址
b() #我是可怜的a, b()执行a里面的函数,




# 2.函数名可以赋值给其他变量
def a():
print("我是可怜的a")

b = a
b()

# 3.函数名可以当做容器类的元素

def func1():
print("我是fun1")
def func2():
print("我是func2")
def func3():
print("我是func3")


lst = [func1, func2, func3]
print(lst) # [<function func1 at 0x000001F9D8601EA0>, <function func2 at 0x000001F9DA2C5EA0>, <function func3 at 0x000001F9DA2C5F28>]
for i in lst:
i()
# 我是fun1
# 我是func2
# 我是func3

# 4.函数名可以当做函数的参数

# 代理模式
# 装饰器的雏形
# 把函数名当成变量来使用
def chi(fn):
print("开挂")
fn()
print(fn.__name__)
print("洗包")

def play_dnf():
print("疯狂的刷")

def func1():
print("我是func1")

def func2():
print("我是func2")

def he():
print("我要喝酒")

chi(he)

def outer():
def inner():
print("哈哈")
return inner()
outer()()

def func():
print("吃了么")
def func2(fn):
print("我是func2")
func()
print("我是func2")
func2(func)

# 5.函数名可以作为函数的返回值

def outer():
def inner():
print("我是inner")

return inner

ret = outer()
print(ret) #<function outer.<locals>.inner at 0x000001A7909920D0>
ret() #我是inner

def func_1():
print("这里是函数1")
def func_2():
print("这里是函数2")
print("这里是函数1")
return func_2

fn = func_1()
print(fn)
fn()

def yue():
print("1. 打开手机")
print("2. 打开微信")
print("3. 找个漂亮的小姐姐")
print("4. 探讨一下人生")
print("5. 一起出来happy")
return "漂亮的小姐姐","大妈", "大爷", "鲜肉" # 返回到哪儿了???? 谁调用的就返回给谁

ret = yue() # ('漂亮的小姐姐', '大妈', '大爷', '鲜肉')
print(ret)

# 1. 打开手机
# 2. 打开微信
# 3. 找个漂亮的小姐姐
# 4. 探讨一下人生
# 5. 一起出来happy
# ('漂亮的小姐姐', '大妈', '大爷', '鲜肉')

# 闭包,就是内层函数对外层函数(非全局)地变量的引用,叫闭包
# 作用
# 1.保护我们的变量不受侵害
# 2.可以让一个变量常驻内存

a = 10
def func1():
print(a)

def func2():
print(a)

func1()

# 你的同事搞事情
def func3():
global a
a = 20

func3()

func2()

def func():
a = 10 # 安全的
def func2():
print(a)
def func3():
print(a)
def func4():
nonlocal a
a = 20

# 什么是闭包
def func1():
name = 'alex'
def func2():
print(name)
func2()
func1()

# 我们可以使用__closure__来检测函数是否是闭包,使用函数名.__closure__返回cell就是闭包,返回None就是不闭包
def func1():
name ="karen"
def func2():
print(name)
func2()
print(func2)
func1()

# karen
# <function func1.<locals>.func2 at 0x000002A176165EA0>

# 如何在函数外边调用内部函数?
def outer():
name = 'karen'
def inner():
print(name)
return inner
fn = outer() # 访问外部函数,获取到内部函数的函数地址
# 1800行代码...
fn() # 访问内部函数,由于fn函数执行的时机是不确定的,必须要保证fn可以正常执行,必须把a保留到最后

# 如果是多层嵌套
def func1():
# def func2():
# def func3():
# print('嘿嘿')
# return func3
# return func2
# func1()()()

# 由它我们可以引出闭包的好处. 由于我们在外界可以访问内部函数. 那这个时候内部函
# 数访问的时间和时机就不⼀一定了了, 因为在外部, 我可以选择在任意的时间去访问内部函数. 这
# 个时候. 想⼀一想. 我们之前说过, 如果⼀一个函数执⾏行行完毕. 则这个函数中的变量量以及局部命名
# 空间中的内容都将会被销毁. 在闭包中. 如果变量量被销毁了了. 那内部函数将不能正常执⾏行行. 所
# 以. python规定. 如果你在内部函数中访问了了外层函数中的变量量. 那么这个变量量将不会消亡.
# 将会常驻在内存中. 也就是说. 使⽤用闭包, 可以保证外层函数中的变量量在内存中常驻. 这样做
# 有什什么好处呢? 非常⼤大的好处. 我们来看⼀一个关于爬⾍虫的代码:
from urllib.request import urlopen

def but():
content = urlopen("http://www.xiaohua100.cn/index.html").read()
def get_content():
return content
return get_content()

fn = but() # 这个时候就开始加载校花100的内容
content = fn() # 获取内容
print(content)

content2 = fn() # 重新获取内容
print(content2)
# 综上,必报的作用就是让一个变量能够常驻内存,供后面的程序使用

def func():
a = 10
def aa():
print("哈哈")
return aa
ret = func()
ret()

# 可迭代的对象
# str, list, tuple, dict, set,open()
# int中没有__iter__
# 可迭代对象dir(可迭代对象)里面都有__iter__函数
# 可以通过isinstance()函数来查看一个对象是什么类型的
lst = ["汉高祖", "清高祖", "明高祖", "哈哈", "娃哈哈", "爽歪歪"]
it = lst.__iter__()
print(it) #<list_iterator object at 0x0000024B2FC7A2B0>迭代器

print(dir(it))

print(it.__next__())
print(it.__next__())
print(it.__next__())
print(it.__next__())
print(it.__next__())
print(it.__next__())
print(it.__next__()) #StopIteration

# for 循环内部的代码
it = lst.__iter__()
# while 1:
# try:
# el = it.__next__()
# except StopIteration:
# break

# 三个特点
# 1.节省内存(生成器)
# 2.惰性机制,必须使用__next__()来获取数据
# 3.只能往前,不能后退

it = lst.__iter__()
print(it.__next__())
print(it.__next__())
print(it.__next__())
print("回去")
it = lst.__iter__() # 重新获取迭代器
print(it.__next__())

# list(内部有for循环)
# for内部 迭代器

lst = [1,55,5,55,5,5,5,555,55,555]
ll = list(set(lst))
print(ll)


list(1) # 'int' object is not iterable

# 如何判断一个数据是否是可迭代对象
# 1. dir() -> __iter__ 可迭代的
# dir() -> __next__ 迭代器
lst = ["秦始皇", "汉武帝", "孝文帝", "隋炀帝", "李世民"]
print("__iter__" in dir(lst))
print("__next__" in dir(lst))

print("__iter__" in dir(int))
print("__next__" in dir(int))
#
it = lst.__iter__()
print("__iter__" in dir(it))
print("__next__" in dir(it))

lst = ["秦始皇", "汉武帝", "孝文帝", "隋炀帝", "李世民"]
# # collections 关于集合类的相关操作
# # Iterable : 可迭代的
# # Iterator : 迭代器
from collections import Iterable, Iterator
print(isinstance(lst, Iterable))
print(isinstance(lst, Iterator))

print(isinstance({1,2,3}, Iterable))

# 我们可以把要迭代的内容当成⼦子弹. 然后呢. 获取到迭代器__iter__(), 就把⼦子弹都装在弹夹
# # 中. 然后发射就是__next__()把每⼀一个⼦子弹(元素)打出来. 也就是说, for循环的时候. ⼀一开始的
# # 时候是__iter__()来获取迭代器. 后⾯面每次获取元素都是通过__next__()来完成的. 当程序遇到
# # StopIteration将结束循环.
原文地址:https://www.cnblogs.com/zero-zero-zero/p/9885753.html