1.装饰器和函数的一些用法
from functools import wraps def wrapper(func): @wraps(func) def inner(): func() return inner @wrapper def func1(): '''jisfhsdkfkd''' print('ddf') print(func1.__name__) func1() print(func1.__doc__) # def index(): # '''这是一个主页信息''' # print('from index') # # print(index.__doc__) #查看函数注释的方法 # print(index.__name__) #查看函数名的方法
2.装饰器带参数
FLAG = True def out(flag): def wrapper(func): def inner(): if flag: print(123) func() else: func() return inner return wrapper @out(FLAG) def func1(): '''jisfhsdkfkd''' print('ddf') func1()
3.多层装饰器
def wrapper1(func): def inner1(): print('wrapper1 ,before func') ret = func() print('wrapper1 ,after func') return ret return inner1 def wrapper2(func): def inner2(): print('wrapper2 ,before func') ret = func() print('wrapper2 ,after func') return ret return inner2 def wrapper3(func): def inner3(): print('wrapper3 ,before func') ret = func() print('wrapper3 ,after func') return ret return inner3 @wrapper3 @wrapper2 @wrapper1 def f(): print('in f') return '哈哈哈' print(f()) 执行结果 wrapper3 ,before func wrapper2 ,before func wrapper1 ,before func in f wrapper1 ,after func wrapper2 ,after func wrapper3 ,after func 哈哈哈
4.刷2道题
# 1.编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件), # 要求登录成功一次,后续的函数都无需再输入用户名和密码 # FLAG = False # def login(func): # def inner(*args,**kwargs): # global FLAG # '''登录程序''' # if FLAG: # ret = func(*args, **kwargs) # return ret # else: # username = input('username:') # password = input('password:') # if username == 'boss_gold' and password == '22222': # FLAG = True # ret = func(*args,**kwargs) # return ret # else: # print('登录失败') # return inner # @login # def shop_add(): # print('增加一件物品') # @login # def shop_del(): # print('删除一件物品') # shop_add() # shop_del() # 2.编写装饰器,为多个函数加上记录调用功能,要求每次调用函数都将被调用的函数名称写入文件 def log(func): def inner(*args,**kwargs): with open('log','a',encoding = 'utf-8') as f: f.write(func.__name__ + '\n') ret = func(*args,**kwargs) return ret return inner @log def shop_add(): print('增加一件物品') @log def shop_del(): print('删除一件物品') shop_add() shop_del()
# 1.编写下载网页内容的函数,要求功能是:用户传入一个url,函数返回下载页面的结果 # 2.为题目1编写装饰器,实现缓存网页内容的功能: # 具体:实现下载的页面存放于文件中,如果文件内有值(文件大小不为0),就优先从文件中读取网页内容,否则,就去下载,然后存到文件中 import os from urllib.request import urlopen def cache(func): def inner(*args,**kwargs): if os.path.getsize('web_cache'): with open('web_cache','rb') as f: return f.read() ret = func(*args,**kwargs) with open('web_cache','wb') as f: f.write(b'***'+ret) return ret return inner @cache def get(url): code = urlopen(url).read() return code ret = get('http://www.baidu.com') print(ret) ret = get('http://www.baidu.com') print(ret)
5.从生成器中取值的几个方法
# next
# for
# 数据类型的强制转换 : 占用内存
def generator(): for i in range(20): yield '哇哈哈%s'%i g = generator() #调用生成器函数得到一个生成器 print(list(g))# 数据类型的强制转换 : 占用内存 # ret = g.__next__() #每一次执行g.__next__就是从生成器中取值,预示着生成器函数中的代码继续执行 # print(ret) # num = 0 # for i in g: # num += 1 # if num > 5: # break # print(i)
6 .#生成器函数进阶
#send 获取下一个值的效果和next基本一致
#只是在获取下一个值的时候,给上一yield的位置传递一个数据
#使用send的注意事项
# 第一次使用生成器的时候 是用next获取下一个值
# 最后一个yield不能接受外部的值
def generator(): print(123) content = yield 1 print(content) print(456) yield 2 print(789) g = generator() print(g.__next__()) print(g.send('hello')) print(g.send('hello'))
7.计算移动平均值
def average(): sum = 0 count = 0 avg = 0 while 1: num = yield avg sum = sum + num count += 1 avg = sum/count avg_g = average() avg_g.__next__() avg1 = avg_g.send(10) # avg1 = avg_g.send(50) print(avg1)
计算移动平均值---预激协程的装饰器
#这个装饰器的目的就是提前激活程序g.__next__() #方便客户计算的时候不用再执行g.__next__() # def init(func): #装饰器 # def inner(*args,**kwargs): # g = func(*args,**kwargs) #g = average() # g.__next__() # return g # return inner # # @init # def average(): # sum = 0 # count = 0 # avg = 0 # while True: # num = yield avg # sum += num # 10 # count += 1 # 1 # avg = sum/count # # avg_g = average() #===> inner # ret = avg_g.send(10) # print(ret) # ret = avg_g.send(20) # print(ret)
8.yield from
def generator(): a = 'adfgg' b = 'dskdl' for i in a:#两句话相当于==》yield from a yield i#两句话相当于==》yield from a for i in b: yield i g = generator() for i in g: print(i)
9.列表推导式和生成器表达式
总结:
1.把列表解析的[]换成()得到的就是生成器表达式
2.列表解析与生成器表达式都是一种便利的编程方式,只不过生成器表达式更节省内存
3.Python不但使用迭代器协议,让for循环变得更加通用。大部分内置函数,也是使用迭代器协议访问对象的。例如, sum函数是Python的内置函数,该函数使用迭代器协议访问对象,而生成器实现了迭代器协议,所以,我们可以直接这样计算一系列值的和:
# egg_list = ['鸡蛋%s' %i for i in range(10)]#列表解析 # print(egg_list) # egg_tur = ('鸡蛋%s' %i for i in range(10))#生成器表达式 # print(egg_tur) # print(egg_tur.__next__()) # print(next(egg_tur)) #next本质就是调用__next__ # print(egg_tur.__next__()) t = sum(x ** 2 for x in range(4)) print(t) s = sum([x ** 2 for x in range(4)]) print(s) m = sum((0,1,4,9)) print(m) print(sum((1,2)))
#[每一个元素或者是和元素相关的操作 for 元素 in 可迭代数据类型] #遍历之后挨个处理 #[满足条件的元素相关的操作 for 元素 in 可迭代数据类型 if 元素相关的条件] #筛选功能 # #30以内所有能被3整除的数 # print([i for i in range(30) if i%3 == 0]) # print((i for i in range(30) if i%3 == 0)) # # 例三:找到嵌套列表中名字含有两个‘e’的所有名字 # names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'], # ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']] # ret = [name for lst in names for name in lst if name.count('e') ==2] # # ret = (name for lst in names for name in lst if name.count('e') ==2) # print(ret) # #字典推导式 # 例一:将一个字典的key和value对调 # dic = {'a':10,'b':20} # dic_reverse = {dic[k]:k for k in dic} # print(dic_reverse) # # 例二:合并大小写对应的value值,将k统一成小写 # d = {'s':10} # print(d.get('b',0)) # print(d.get('s')) # mcase = {'a': 10, 'b': 34, 'A': 7, 'Z': 3} # s = {k.lower():mcase.get(k.lower(),0) + mcase.get(k.upper(),0) for k in mcase} # print(s) #集合推导式,自带结果去重功能 # s = {x**2 for x in [1,2,-1]} # print(s) # squared = {x**2 for x in [1, -1, 2]} # print(squared) #各种推导式 : 生成器 列表 字典 集合 #遍历操作 #筛选操作
10.生成器Generator:
本质:迭代器,所以拥有__iter__方法和__next__方法
特点:惰性运算,开发者自定义
使用生成器的优点:
1.延迟计算,一次返回一个结果。也就是说,它不会一次生成所有的结果,这对于大数据量处理,将会非常有用。
2.提高代码可读性
print(sum([i for i in range(100)]))#内存占用大,机器容易卡死 print(sum(i for i in range(100000)))#几乎不占内存 print(i for i in range(100))#几乎不占内存
11.刷题
# 3.处理文件,用户指定要查找的文件和内容,将文件中包含要查找内容的每一行都输出到屏幕 # def func(filename,s): # with open(filename,encoding = 'utf-8') as f1: # for i in f1: # if s in i: # yield i # # g = func('ss','生成器') # for i in g: # print(i.strip()) # def check_file(filename,aim): # with open(filename,encoding='utf-8') as f: #句柄 : handler,文件操作符,文件句柄 # for i in f: # if aim in i: # yield i # # g = check_file('1.复习.py','生成器') # for i in g: # print(i.strip()) # 4.写生成器,从文件中读取内容,在每一次读取到的内容之前加上‘***’之后再返回给用户。 # def check_file(filename): # with open(filename,encoding='utf-8') as f: #句柄 : handler,文件操作符,文件句柄 # for i in f: # yield '***'+i # # for i in check_file('1.复习.py'): # print(i.strip()) def func(filename): with open(filename,encoding = 'utf-8') as f1: for i in f1: yield '***'+i g = func('ss') for i in g: print(i.strip())
12.生成器表达式面试题
# def demo(): # for i in range(4): # yield i # # g=demo() # # g1=(i for i in g) # g2=(i for i in g1) # # print(list(g)) # print(list(g1)) # print(list(g2)) def add(n,i): return n+i def test(): for i in range(4): yield i g=test() # for n in [1,10,5]: # g=(add(n,i) for i in g) n = 1 g=(add(n,i) for i in test()) n = 10 g=(add(n,i) for i in (add(n,i) for i in test())) n = 5 g=(15,16,17,18) print(list(g))
13.内置函数
作用域相关
基于字典的形式获取局部变量和全局变量
globals()——获取全局变量的字典
locals()——获取执行本方法所在命名空间内的局部变量的字典
# print() # input() # len() # type() # open() # tuple() # list() # int() # bool() # set() # dir() # id() # str() # print(locals()) #返回本地作用域中的所有名字 # print(globals()) #返回全局作用域中的所有名字 # global 变量 # nonlocal 变量 #迭代器.__next__() # next(迭代器) # 迭代器 = iter(可迭代的) # 迭代器 = 可迭代的.__iter__() # range(10) # range(1,11) # print('__next__' in dir(range(1,11,2))) # dir 查看一个变量拥有的方法 # print(dir([])) # print(dir(1)) # help # help(str) # 变量 # print(callable(print)) # a = 1 # print(callable(a)) # print(callable(globals)) # def func():pass # print(callable(func)) import time # t = __import__('time') # print(t.time()) # 某个方法属于某个数据类型的变量,就用.调用 # 如果某个方法不依赖于任何数据类型,就直接调用 —— 内置函数 和 自定义函数 # f = open('1.复习.py') # print(f.writable()) # print(f.readable()) #id #hash - 对于相同可hash数据的hash值在一次程序的执行过程中总是不变的 # - 字典的寻址方式 # print(hash(12345)) # print(hash('hsgda不想你走,nklgkds')) # print(hash(('1','aaa'))) # print(hash([])) # ret = input('提示 : ') # print(ret) # print('我们的祖国是花园',end='') #指定输出的结束符 # print('我们的祖国是花园',end='') # print(1,2,3,4,5,sep='|') #指定输出多个值之间的分隔符 # f = open('file','w') # print('aaaa',file=f) # f.close() # import time # for i in range(0,101,2): # time.sleep(0.1) # char_num = i//2 # per_str = '\r%s%% : %s\n' % (i, '*' * char_num) \ # if i == 100 else '\r%s%% : %s' % (i,'*'*char_num) # print(per_str,end='', flush=True)
14.进度条
#进度条子 import time for i in range(0,101,2): time.sleep(0.1) char_num = i//2 per_str = '\r%s%% : %s\n' % (i, '*' * char_num) \ if i == 100 else '\r%s%% : %s' % (i,'*'*char_num) print(per_str,end='', flush=True)