1复习
# 函数 —— 2天
# 函数的定义和调用
# def 函数名(形参):
#函数体
#return 返回值 #被调用的地方接收
#调用 函数名(实参)
# 站在形参的角度上 : 位置参数,*args,默认参数(陷阱),**kwargs
# 站在实参的角度上 : 按照位置传,按照关键字传
# 返回值:没有返回值 返回一个值 返回多个值
# 接收返回值:没有返回值不接收,返回一个值用一个变量接收,返回多个值用一个变量或者对应数目的变量接收
# 闭包函数 —— 在内部函数引用外部函数的变量
# 装饰器函数—— 装饰器一定是闭包函数
# 装饰器的作用 : 在不改变原来函数的调用方式的情况下 在这个函数的前后添加新的功能
# 完美的符合了一个开发原则 :开放封闭原则
# 对扩展是开发的
# 对修改是封闭的
# 基础的装饰器
# from functools import wraps
# def wrapper(func):
# @wraps(func)
# def inner(*args,**kwargs):
# '''在函数被调用之前添加的代码'''
# ret = func(*args,**kwargs) # func是被装饰的函数 在这里被调用
# '''在函数被调用之后添加的代码'''
# return ret
# return inner
# 使用 —— @wrapper
# @wrapper
# def func(): #inner
# pass
#
# func.__name__
# 带参数的装饰器
# @wrapper -- > @warapper(argument)
# 三层嵌套函数
# def outer(形参):
# def wrapper(func):
# def inner(*args,**kwargs):
# '''在函数被调用之前添加的代码'''
# ret = func(*args,**kwargs) # func是被装饰的函数 在这里被调用
# '''在函数被调用之后添加的代码'''
# return ret
# return inner
# return wrapper
# @outer(True)
# def func():
# pass
# 多个装饰器装饰一个函数
# 俄罗斯套娃
#def wrapper1(func):
# @wraps(func)
# def inner(*args,**kwargs):
# print('before 1')
# print('******')
# ret = func(*args,**kwargs) # func是被装饰的函数 在这里被调用
# '''在函数被调用之后添加的代码'''
# return ret
# def wrapper2(func):
# @wraps(func)
# def inner(*args,**kwargs):
# print('before 2')
# ret = func(*args,**kwargs) # func是被装饰的函数 在这里被调用
# '''在函数被调用之后添加的代码'''
# return ret
# @wrapper1
# @wrapper2
# def func():
# print('111')
# 迭代器和生成器 —— 两天
# 内置函数 —— 两天
2迭代器
1双下方法
#双下方法
print([1].__add__([2]))
print([1]+[2])
<<<
[1, 2]
[1, 2]
#list dic str set tuple range enumerate
print(dir([])) #告诉我列表的所有方法
ret=set(dir([]))&set(dir({}))&set(dir(""))&set(dir(range(12)))
print(ret)
print(set(dir([]))-set(dir({})))
<<<
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
{'__gt__', '__reduce_ex__', '__doc__', '__getitem__', '__len__', '__sizeof__', '__new__', '__eq__', '__delattr__', '__str__', '__reduce__', '__format__', '__repr__', '__ne__', '__le__', '__lt__', '__iter__', '__getattribute__', '__init__', '__contains__', '__subclasshook__', '__setattr__', '__dir__', '__class__', '__ge__', '__init_subclass__', '__hash__'}
{'__iadd__', '__imul__', '__mul__', 'count', 'index', 'sort', 'reverse', 'append', '__rmul__', 'extend', 'remove', 'insert', '__reversed__', '__add__'}
'''
可迭代协议:
只要能被for循环的数据类型 就一定有__iter__方法 []
iterable 只要含有__iter__方法的都是可迭代的
迭代器协议:
一个列表执行了__iter__()之后的返回值就是一个迭代器 [].__iter__
iteraor 内部含有__iter__和__next__方法的就是迭代器
通过__next__()就可以从迭代器中一个一个取值 :print(iterator.__next__())
for:
for循环其实就是在使用迭代器
只有是可迭代对象的时候才能用for
当我们用一个新的变量 不确定能不能for循环的时候 就判断是否可迭代
判断方法 from _collections_abc import
Iterable print(isinstance([],Iterable))
print('__iter__'in dir([])) '''
2协议
#协议
print([].__iter__()) #打印迭代器直接给你内存地址
print(set(dir([].__iter__()))-set(dir([]))) #列表迭代器相当于列表的独特方法
print([1,'a','bbb'].__iter__().__length_hint__()) #__length_hint__求元素个数
l=[1,2,3]
iterator=l.__iter__()
print(iterator.__next__())
print(iterator.__next__())
print(iterator.__next__())
<<<
<list_iterator object at 0x0000026048DF4438>
{'__setstate__', '__next__', '__length_hint__'}
3
1
2
3
3判断方法
#判断方法
print('__iter__'in dir([]))
print('__iter__'in dir([].__iter__()))
from _collections_abc import Iterable #弃用警告:不推荐使用或导入来自collections
from collections.abc import Iterator #而不是“collections.abc”中的ABC
print(isinstance([],Iterator)) # 并且在python3.8中它将停止工作
print(isinstance([],Iterable)) #判断[]是不是可迭代的
<<<
True
True
False
True
4for
#for
#只要有iter方法就能被循环 for循环其实就是在使用迭代器
l=[1,2,3]
for i in l.__iter__():
print(i)
print([].__iter__()) #打印迭代器直接给你内存地址
print(range(10).__iter__())
print(range(10))
l=[1,2,3]
for i in l:
print(i)
if i ==2:
break
<<<
1
2
3
<list_iterator object at 0x0000024B1E314208>
<range_iterator object at 0x0000024B1DFAD830>
range(0, 10)
1
2
5迭代器的好处
# 迭代器的好处
'''
从容器类型中一个个取值 会把所有值都取到
节省内存空间
迭代器并不会在内存中占一大块内存
而是随着循环 每次生成一个next给我一个'''
l=[1,2,3,4]
iterator=l.__iter__()
while 1:
print(iterator.__next__())
<<<
Traceback (most recent call last):
File "C:/python全栈/me第一部分/day13 迭代器和生成器.py", line 76, in <module>
print(iterator.__next__())
StopIteration
1
2
3
4
print(range(10000))
print(list(range(3)))
def f():
for i in range(200):
i="wahaha%s"%i
return i
print(f())
<<<
range(0, 10000)
[0, 1, 2]
wahaha199
3.生成器
#3 生成器
#生成器函数 本质上就是我们自己写的函数
#只要含有yield关键字的函数都是生成器函数
#yield不能和return共用且需要写在函数内
def generetor():
print(1)
yield 'a'
ret=generetor()
print(ret)
print(ret.__next__())
<<<
<generator object generetor at 0x00000246FE4C8A98>
1
a
1.生成器函数 执行之后会得到一个生成器作为一个返回值
#生成器函数 执行之后会得到一个生成器作为一个返回值
def generetor1():
print(1)
yield 'a'
print(2)
yield 'b'
yield 'c'
g=generetor1()
print(g)
ret=g.__next__()
print(ret)
# for i in g:
# print(i) 1 a 2 b c
ret=g.__next__()
print(ret)
ret = g.__next__()
print(ret)
<<<
1
a
2
b
c
2.next方法获取生成器的值
# 娃哈哈
import time
def wahaha():
for i in range(200000):
yield '娃哈哈%s'% i
g=wahaha()
g1=wahaha()
print(g.__next__())
print(g.__next__())
print(g1.__next__())
g=wahaha()
count=0
a=time.time()
for i in g:
count+=1
print(i)
if count>3:
break
b=time.time()
print(b-a)
print("***",g.__next__())
for i in g:
count+=1
print(i)
if count>6:
break
print("&&",g.__next__())
<<<
娃哈哈0
娃哈哈1
娃哈哈0
娃哈哈0
娃哈哈1
娃哈哈2
娃哈哈3
0.0
*** 娃哈哈4
娃哈哈5
娃哈哈6
娃哈哈7
&& 娃哈哈8
4 利用生成器监听文件输入
#4 利用生成器监听文件输入
def tail(filename):
f=open(filename,encoding='utf-8')
while True:
line=f.readline()
if line.strip():
yield line.strip() #使用生成器在后面的操作中更灵活想加*就加
g=tail('file')
# print(g.__next__())
for i in g:
if 'python' in i:
print("***",i)
<<<
*** python