代码改变世界

函数 之 闭包 迭代器 推到式 装饰器 生成器 推到式

2018-11-15 19:11  职业冒险家  阅读(186)  评论(0编辑  收藏  举报
闭包:
def func():
name = "alex" # 常驻内存 防止其他程序改变这个变量
def inner():
print(name) # 在内层函数中调用了外层函数的变量,叫闭包, 可以让一个局部变量常驻内存
     print(inner.__closure__)    # 查看inner是否是闭包, 如果有东西就是闭包, 没东西就不是闭包
  return inner
func()()
ret = func()
ret() # 执行的是inner()

迭代器 与可迭代: https://www.cnblogs.com/Eva-J/p/7277026.html
# for i in 123:
# print(i)#b报错 因为不是可迭代
# 可迭代对象: str, list, tuple, set, f, dict
# 所有的以上数据类型中都有一个函数__iter__(), 所有包含了__iter__()的数据类型都是可迭代的数据类型 Iterable
# dir()来查看一个对象,数据类型中包含了哪些东西

# 获取迭代器 .__iter__()

it=list.__iter__()
迭代器往外拿元素. __next__()
print(it.__next__())    # 皇阿玛

lst = ["皇阿玛", "皇额娘", "容嬷嬷", "紫薇"]
# 模拟for循环
it = lst.__iter__()
print(it)
while True:
try:
name = it.__next__()
print(name)
except StopIteration: # 拿完了
break

from collections import Iterable    # 可迭代的
from collections import Iterator # 迭代器
isinstence(对象, 类型) 判断xx对象是否是xxx类型的
# it = lst.__iter__()
# print(isinstance(it, Iterable)) # 判断是否是可迭代的 迭代器一定是可迭代的
# print(isinstance(it, Iterator)) # 迭代器里面一定有__next__(), __iter__()
# print("__iter__" in dir(lst))   # 确定是一个可迭代的
# print("__next__" in dir(lst)) # 确定是不是一个迭代器

f = open("01 今日内容大纲",mode="r", encoding="utf-8")
print(isinstance(f, Iterable))
print(isinstance(f, Iterator))

文件也是一个迭代器
 装饰器
.对扩展是开放的

    为什么要对扩展开放呢?


    我们说,任何一个程序,不可能在设计之初就已经想好了所有的功能并且未来不做任何更新和修改。所以我们必须允许代码扩展、添加新功能。


  2.对修改是封闭的


    为什么要对修改封闭呢?


    就像我们刚刚提到的,因为我们写的一个函数,很有可能已经交付给其他人使用了,如果这个时候我们对其进行了修改,很有可能影响其他已经在使用该函数的用户。


装饰器完美的遵循了这个开放封闭原则。

在不改变函数调用方式的基础上在函数的前、后添加功能。

from functools import wraps

def deco(func):
    @wraps(func) #加在最内层函数正上方
    def wrapper(*args,**kwargs):
        return func(*args,**kwargs)
    return wrapper

@deco
def index():
    '''哈哈哈哈'''
    print('from index')

print(index.__doc__)
print(index.__name__)

装饰器——wraps demo
固定格式
def timer(func):
    def inner(*args,**kwargs):
        '''执行函数之前要做的'''
        re = func(*args,**kwargs)
        '''执行函数之后要做的'''
        return re
    return inner

from functools import wraps

def deco(func):
    @wraps(func) #加在最内层函数正上方
    def wrapper(*args,**kwargs):
        return func(*args,**kwargs)
    return wrapper

装饰器的固定格式——wraps版
def wrapper1(func):
    def inner():
        print('wrapper1 ,before func')
        func()
        print('wrapper1 ,after func')
    return inner

def wrapper2(func):
    def inner():
        print('wrapper2 ,before func')
        func()
        print('wrapper2 ,after func')
    return inner

@wrapper2
@wrapper1
def f():
    print('in f')

f()

多个装饰器装饰同一个函数


 # z重点 return 直接返回结果. 结束函数的调用
# z重点 yield 返回结果.可以让函数分段执行
#
def func():
lst = []
for i in range(1,10):
lst.append("衣服%s" % i)
return lst
print(func())

def gen():
i = 1
while i < 10:
yield "衣服%s" % i
i = i + 1
g = gen()
print(g.__next__())
print(g.__next__())
print(g.__next__())
print(g.__next__())
print(g.__next__())
print(g.__next__())
print(g.__next__())
 # __next__() 可以让生成器向下执行一次
# send() 也可以让生成器向下执行一次, 给上一个yield传一个值, 第一个不能用send(). 最后一个也不要传
# 值
 def eat():
print("我吃什么啊")
a = yield "馒头"
print("a=",a)
b = yield "大饼"
print("b=",b)
c = yield "韭菜盒子"
print("c=",c)
yield "GAME OVER"

gen = eat() # 获取成器
ret1 = gen. __next__ ()
print(ret1) #我吃什么呀 馒头
ret2 = gen.send("胡辣汤")
print(ret2) #a=胡辣汤,大饼
ret3 = gen.send("狗粮")
print(ret3)#b-=狗粮 韭菜盒子
ret4 = gen.send("猫粮")
print(ret4) #c=猫粮,gameover
 def func():
yield 11
yield 22
yield 33
yield 44
g = func()
lst=list(g)
print(lst) #[11, 22, 33, 44]
# lst = list(g) # 可迭代对象

这一点 不懂

# 列表推倒式; 最终给你的是列表
# 语法 [最终结果(变量) for 变量 in 可迭代对象]

# . 100以内能被3整除的数的平方
# lst = [i*i for i in range(1,101) if i % 3 == 0]
# . 寻找名字中带有两个e的的名字
names = [['Tom', 'Billy', 'Jefferson' , 'Andrew' , 'Wesley' , 'Steven' ,
'Joe'],['Alice', 'Jill' , 'Ana', 'Wendy', 'Jennifer', 'Sherry' , 'Eva']]
推到式:lst=[name for firs in names for name in firs if name.count("e")>=2]
print(lst)
lst=[]
for循环:for first in names:
for name in first:
if name.count("e")>=2:
lst.append(name)
print(lst)

gen =("马化腾我第%s次爱你" % i for i in range(1,11))
#print(tuple(gen))
#print(list(gen))
for i in gen:
print(i)
面试题  
def add(n,i):
    return n+i

def test():
    for i in range(4):
        yield i

g=test()
for n in [1,10]:
    g=(add(n,i) for i in g)

print(list(g))  惰性机制 所以输出[20, 21, 22, 23]