第1章 函数对象
一 函数是第一类对象,即函数可以当作数据传递
#1 可以被引用
#2 可以当作参数传递
#3 返回值可以是函数
#3 可以当作容器类型的元素
def select(sql):
print('执行select:',sql)
def insert(sql):
print('执行insert: ',sql)
def update(sql):
print('执行update',sql)
def delete(sql):
print('执行delete',sql)
cmd_dict={
'select':select,
'insert':insert,
'update':update,
'delete':delete
}
def main():
while True:
sql=input('>>>: ').strip()
if not sql:continue
cmd_info=sql.split() ### 截取sql
cmd=cmd_info[0] ### 获得sql语句中索引0的内容即select、insert、delete、update
if cmd in cmd_dict:
cmd_dict[cmd](cmd_info) ### 判断匹配cmd的值存在字典中的key 那么就可以执行调用,并且对应一个value方法
else: ### 随着方法功能的增多,这段逻辑不需要改动
print('命令不存在')
main()
1.1 优雅的取代多分支if...else
def boo(str):
print('执行boo',str)
def main():
dict={
'foo':foo,
'boo':boo
}
while True:
cmd=input('cmd>>>: ').strip()
if not cmd:continue
if cmd in dict:
dict[cmd](cmd)
main()
第2章 嵌套函数
### 函数的嵌套调用:在调用一个函数的过程中,又调用了其他函数
### 执行顺序是: 先执行 foo里的 print('from foo') 然后在函数中调用了bar函数,执行bar的 int('from bar')
def bar():
print('from bar')
def foo():
print('from foo')
bar()
foo()
### 调用自己就是递归
### 嵌套的用法实例 求四个值的最大值:
### 求两个值的最大值
def max2(x,y):
if x > y:
return x
else:
return y
### 求四个值的最大值,就可以调用2个最大值的方法
### 分解操作,先求两个 再往后走
def max4(a,b,c,d):
res1=max2(a,b)
res2=max2(res1,c)
res3=max2(res2,d)
return res3 ### 最后返回最终结果
print(max4(1,2,3,-1))
### 函数的嵌套定义:在一个函数的内部,又定义了另外一个函数
### 为什么外部无法直接找到f2函数? 因为外部只有在调用f1的时候f2才生效,这涉及到 名称空间 知识点
def f1():
x=1 ### 定义一个变量,属于f1函数,只在函数的时候生效
def f2(): ### 在函数的内部定义了一个f2函数,把他看成一个变量 加括号可以调用~
print('from f2')
print(x)
f2() ### 调用时才有效 先找到f2,然后加括号运行
f1()
#print(x) ### 无法打印到这个x 因为x在函数中定义的,调用函数结束后就失效了
第3章 名称空间
### 名称空间:存放名字的地方,
### 准确的说,名称空间是存放名字与变量值绑定关系的地方
# 名称空间
# - 分三种
# 内置名称空间:python解释器启动则生效
# 全局名称空间:执行python文件时生效
# 局部名称空间:调用函数时,临时生效,函调用结束则失效
# - 加载顺序:先内置,再全局,最后有可能产生局部
# - 查找名字的顺序:先局部,再全局,最后内置
# 强调:作用关系在函数定义阶段就已经固定,与调用位置无关
x=0
def f1():
x=1
def f2():
x=2
def f3():
x=3
print(x)
f3()
f2()
f1()
第4章 作用域
### 作用域:作用的范围
# 1、全局作用域:全局存活,全局有效
max=111
def f1():
def f2():
def f3():
def f4():
print(max)
f4()
f3()
f2()
f1()
# 2、局部作用域:临时存活,局部有效,只能在函数内访问
max=111
def f1():
def f2():
def f3():
def f4():
max=444
print(max)
f4()
f3()
f2()
f1()
4.1 查看局部作用域名字 locals
def f1():
x=1
y=2
def f2():pass
print(locals())
f1()
{'f2': <function f1.<locals>.f2 at 0x000000A3D14698C8>, 'y': 2, 'x': 1}
4.2 查看全局作用域的名字 globals
z=1
def f1():
x=1
y=2
def f2():pass
# print(locals())
print(globals())
f1()
...'z': 1, 'f1': <function f1 at 0x0000008567283E18>
### 全局的局部 依然是全局
print(locals() is globals())
True
4.3 内置名称空间在作用域
'__builtins__': <module 'builtins' (built-in)>,
print(globals()['__builtins__'])
<module 'builtins' (built-in)> ### 模块
### 查看模块下的内置方法 dir
print(dir(globals()['__builtins__']))
['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning', 'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError', 'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False', 'FileExistsError', 'FileNotFoundError', 'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning', 'IndentationError', 'IndexError', 'InterruptedError', 'IsADirectoryError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'ModuleNotFoundError', 'NameError', 'None', 'NotADirectoryError', 'NotImplemented', 'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError', 'RecursionError', 'ReferenceError', 'ResourceWarning', 'RuntimeError', 'RuntimeWarning', 'StopAsyncIteration', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'TimeoutError', 'True', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'WindowsError', 'ZeroDivisionError', '__build_class__', '__debug__', '__doc__', '__import__', '__loader__', '__name__', '__package__', '__spec__', 'abs', 'all', 'any', 'ascii', 'bin', 'bool', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'exec', 'exit', 'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type',
'vars', 'zip']
4.4 关键字 golbal nonlocal
x=1
def f1():
global x ### 使用全局变量 尽量避免局部修改全局的变量名
x=2
f1()
print(x)
>>> 2
l=[]
def f2():
l.append('f2') ### 因为列表是可变类型,所以直接修改了全局的l列表
f2()
print(l)
### 针对全局的不可变类型 修改的话要加 golbal ,针对可变类型直接修改即可
### 修改局部
x=0
def f1():
x=1
def f2():
x=2
def f3():
global x
x=3
f3()
f2()
f1()
print(x)
x=0
def f1():
x=1
def f2():
x=2
def f3():
global x
x=3
print(x)
f3()
f2()
f1()
>>> 2
### 跳出当前这一层函数 修改上一层函数的变量nonlocal 不能修改全局的
x=0
def f1():
x=1
def f2():
# x=2
def f3():
# global x
nonlocal x
x=3
# print(x)
f3()
f2()
print(x)
f1()
4.5 优先掌握: 作用域关系在函数定义时就已经固定
# 优先掌握:作用域关系 在函数定义时 就已经固定
# 与调用位置无关
### 打破了层级 原本f2只能在f1下使用,但是这样 可以放到外层使用了
x=1
def f1():
def f2():
print(x)
return f2 ### 这个函数被返回出来 打破了层级
func=f1()
# print(func)
x=1000
func() ### func执行的就是f2 在函数里没有x,所以这里引用了执行全局中前最新的1000
>>> 1000
### 回到定义阶段找关系
x=1
def f1():
def f2():
print(x)
return f2 ### 注意 这里返回的是f2 返回的不是结果而是 f2这个函数本身
def foo(func):
x=3000
func() ### f2
foo(f1()) ### 在这里执行f1 实际上是 调用了 上面的f2 那么只运行f2 中的x找不到 找到全局的x=1 所以打印1
第5章 闭包
### 加载顺序:先内置,再全局,最后有可能产生局部
### 查找名字的顺序:先局部,再全局,最后内置
### 作用关系在函数定义阶段就已经固定,与调用位置无关
### 闭包函数:
# 1、定义在函数内部的函数,
# 2、包含对外部作用域名字的引用,而不是对全局作用域名字的引用 那么该内部函数就成为 闭包函数
x=1
def f1():
x=111 ### 如果存在 优先访问
def f2(): ### 内部函数 函数对象的概念 把函数当做返回值返回 打破层级限制
print(x)
return f2
func=f1()
func()
### 原始的传参形式
def wrapper(x):
print(x)
wrapper(123)
### 使用闭包,今后调用都包裹着x=123 和 prinx(x)这些内容
### 闭包形式 给一个函数捆绑一个值
def deco():
x=123
def wrapper():
print(x)
return wrapper
func=deco()
func()
5.1 闭包函数的应用
### 每次执行都需要手动输入函数,比较麻烦,可以使用闭包 就不用每次都传值
import requests #pip3 install requests
# def get(url):
# return requests.get(url).text
# print(get('https://www.python.org'))
### 写成一个专门爬取python的函数方法,定义好直接调用
def index():
url='https://www.python.org' ### 被包含的捆绑参数
def get(): ### 闭包函数
return requests.get(url).text
return get
python_web=index()
python_web() ### 以后就可以随意调用,延迟(惰性)计算
### 上面的闭包函数的url其实是写死了 其实也可以传值 写活
def index(url):
# url='https://www.python.org' ### 被包含的捆绑参数
def get(): ### 闭包函数
return requests.get(url).text #print(requests.get(url).text)
return get
python_web=index('https://www.python.org') ### 传值
baidu_web=index('https://www.baidu.com') ### 传值
python_web()
baidu_web()
第6章 装饰器
### 1、开放封闭原则:对扩展是开放的,对修改是封闭的
### 2、装饰器:装饰他人的工具,装饰器的目的是为其他人添加新功能
### 3、装饰器本身是任意可调用对象,被装饰的对象本身也可以是任意可调用对象
### 装饰器遵循的原则:
# 1、不修改被装饰对象的源代码
# 2、不修改被装饰对象的调用方式
### 装饰器的目的:
# 1、在遵循1和2原则的前提下,为其他新功能函数添加新功能
6.1 模拟打开网页 加装饰器
### 源码就是模拟访问一个页面
import time
def index():
time.sleep(3)
print('welcome to index')
index()
### 现在要加上一个统计打开时间的方法 这样就修改了源码
import time
def index():
start=time.time()
time.sleep(3)
print('welcome to index')
stop=time.time()
print('run time is %s' %(stop-start))
index()
### 如果在写一个统计时间的函数 就修改了调用方法
import time
def index():
time.sleep(3)
print('welcome to index')
def wrapper(func):
start=time.time()
func()
stop=time.time()
print('run time is %s' %(stop-start))
wrapper(index)
import time
def index():
time.sleep(3)
print('welcome to index')
def home():
time.sleep(3)
print('welcome to home')
def timmer(func):
# func=index
def wrapper():
start=time.time()
func()
stop=time.time()
print('run time is %s' %(stop-start))
return wrapper
index=timmer(index)
home=timmer(home)
index()
home()
6.2 简洁的实现装饰器 @装饰器名
### @装饰器名,必须写在被装饰对象的正上方,并且是单独一行
import time
def timmer(func):
# func=index
def wrapper():
start=time.time()
func()
stop=time.time()
print('run time is %s' %(stop-start))
return wrapper
### 把@timmer正下方函数名 当做参数传给timmer函数,把返回值赋值给这个函数
@timmer # index=timmer(index)
def index():
time.sleep(3)
print('welcome to index')
@timmer # home=timmer(home)
def home():
time.sleep(3)
print('welcome to home')
index()
home()
6.3 有参装饰器
### 有参函数装饰器
import time
def timmer(func):
# func=index
def wrapper(*args,**kwargs): ### 没有要求传参,但是下面调用的时候要求传参,如果这里加上name 传给func(home)
### 但是index又不要求你有参数,如何适应各种形式传参,*args,**kwargs 接收任意长度格式的参数
start=time.time()
func(*args,**kwargs) ### 怎么收到 怎么给func
stop=time.time()
print('run time is %s' %(stop-start))
return wrapper
@timmer # index=timmer(index)
def index():
time.sleep(3)
print('welcome to index')
@timmer # home=timmer(home)
def home(name):
time.sleep(3)
print('welcome to home %s' %name)
index()
home('leo') # 其实就是wrapper('name')
6.4 返回值装饰器
### 返回值
### 要在原始方法里增加返回值,然后在闭包调用时候使用
import time
def timmer(func):
# func=index ### 这样就写死了
def wrapper(*args,**kwargs):
start=time.time()
res=func(*args,**kwargs) ### 针对这个函数有返回值 保存给res 然后在执行完成后返回 原始方法里返回什么在这里得到什么
stop=time.time()
print('run time is %s' %(stop-start))
return res
return wrapper
@timmer # index=timmer(index)
def index():
time.sleep(3)
print('welcome to index')
return 123 ### 在index中设置一个返回值
@timmer # home=timmer(home)
def home(name):
time.sleep(3)
print('welcome to home %s' %name)
return 456
res=index() ### 调用的是wrapper 并不是最原始的 所以要在wrapper里增加返回值
print(res) ### 如果不在wrapper增加 那么这里输出返回值是None
res1=home('leo') # 其实就是wrapper('name')
print(res1)
6.5 实现认证功能装饰器
# ### 实现认证功能装饰器
# ### 判断用户名、密码 并且实现与文件中的用户名密码校验 {"leo":"123","lex":"456","rubin":"789"}
current_user={'user':None} ### 记录登录状态
def auth(func):
def wrapper(*args,**kwargs):
if current_user['user']: ### 下次判断user有没有值 有值直接进入页面
return func(*args,**kwargs)
name=input('Please input your name: ').strip()
password=input('Please input your password: ').strip()
with open('user.txt','r',encoding='utf-8') as f:
dic=eval(f.read())
# print(dic,type(dic))
if name in dic and password == dic[name]:
res=func(*args,**kwargs)
current_user['user']=name ### 保存登录状态,保存用户名
return res
else:
print('name or password error')
return wrapper
@auth #index=auth(index)
def index():
print('from index')
@auth
def home(name):
print('welcome %s' %name)
index()
home('leo')
6.6 有参装饰器
### 有参装饰器版本 得有多种验证方式,比如sql、文件等
current_user={'user':None}
### 考虑 怎么把auth_type 传进去 可以再加一层闭包,使用到3层即可
def auth(auth_type='file'): ### 默认参数 不传值走file验证
def deco(func):
def wrapper(*args,**kwargs):
if auth_type =='file': ### 如果验证类型是文件
if current_user['user']:
return func(*args,**kwargs)
name=input('Please input your name: ').strip()
password=input('Please input your password: ').strip()
with open('user.txt','r',encoding='utf-8') as f:
dic=eval(f.read())
# print(dic,type(dic))
if name in dic and password == dic[name]:
res=func(*args,**kwargs)
current_user['user']=name
return res
else:
print('name or password error')
elif auth_type == 'mysql':
print('mysql')
elif auth_type == 'ldap':
print('ldap')
else:
print('not vlaid auth_type')
return wrapper
return deco
@auth(auth_type='mysql') #index=deco(index)
def index():
print('from index')
@auth(auth_type='file')
def hoem(name):
print('welcome %s' %name)
index()
hoem('leo')
6.7 装饰器补充
6.7.1 补充注释
import time
from functools import wraps ### 在装饰器最内层函数上
def timmer(func):
@wraps(func)
def wrapper(*args,**kwargs):
start=time.time()
res=func(*args,**kwargs)
stop=time.time()
print('run index is %s' %(stop - start))
return res
return wrapper
# @timmer #index=timmer(index)
def index():
'''这是index函数'''
time.sleep(3)
print('welcome index')
return 123
# index()
print(index.__doc__) ### 查看注释 加上装饰器看不到只能是node 他看的是wrapper里的doc其实 要让wrapper的注释信息与index一样
# print(help(index)) ### 查看注释
6.7.2 多个装饰器
import time
from functools import wraps ### 在装饰器最内层函数上
current_user={'user':None}
def timmer(func):
@wraps(func)
def wrapper(*args,**kwargs):
start=time.time()
res=func(*args,**kwargs)
stop=time.time()
print('run index is %s' %(stop - start))
return res
return wrapper
def auth(auth_type='file'): ### 默认参数 不传值走file验证
def deco(func):
def wrapper(*args,**kwargs):
if auth_type =='file': ### 如果验证类型是文件
if current_user['user']:
return func(*args,**kwargs)
name=input('Please input your name: ').strip()
password=input('Please input your password: ').strip()
with open('user.txt','r',encoding='utf-8') as f:
dic=eval(f.read())
# print(dic,type(dic))
if name in dic and password == dic[name]:
res=func(*args,**kwargs)
current_user['user']=name
return res
else:
print('name or password error')
elif auth_type == 'mysql':
print('mysql')
elif auth_type == 'ldap':
print('ldap')
else:
print('not vlaid auth_type')
return wrapper
return deco
### 装饰器是修饰最下方,如果先写time 就会修饰auth 所以要分清楚函数中的方法是否有执行时间 谁在上面谁生效
@auth()
@timmer #index=timmer(index)
def index():
'''这是index函数'''
time.sleep(3)
print('welcome index')
return 123
index()
第7章 迭代器
7.1 什么是迭代器
# 迭代:是一个重复的过程,每一次的重复都是基于上一次的结果而来
# 迭代器:不依赖索引的取值方式
# 可迭代对象iterable :凡是对象下有__iter__方法:(对象..__iter__),该对象就是可迭代对象
7.2 字典迭代
dic={'name':'leo','sex':'male','age':28}
i=dic.__iter__()
print(i)
>>> <dict_keyiterator object at 0x0000005695807728>
# iterator 迭代器对象
# <dict_keyiterator object at 0x0000009D419F7728> 这个结果称为 iterator 迭代器对象
dic={'name':'leo','sex':'male','age':28}
i=dic.__iter__()
print(i) # iterator 迭代器对象 # <dict_keyiterator object at 0x0000009D419F7728> 这个结果称为 iterator 迭代器对象
# i.__next__() # next(i) # 字典取值也是无序的 取到了字典的key
print(next(i))
print(next(i))
print(next(i))
# print(next(i)) # 出异常 StopIteration 迭代器没值了
>>> <dict_keyiterator object at 0x000000CE0EBC7728>
>>> name
>>> sex
>>> age
7.3 列表迭代
l=['a','b','c','d','e'] # 列表可迭代对象
i=l.__iter__() # 迭代器对象
print(i)
i1=i.__iter__() # 再赋值一次 发现结果相同
print(i1)
>>> <list_iterator object at 0x000000358B768A90>
>>> <list_iterator object at 0x000000358B768A90>
### 迭代器也有iter方法,本身也是可迭代对象,除了iter还有next方法
l=['a','b','c','d','e'] # 列表可迭代对象
i=l.__iter__() # 迭代器对象
print(i)
i1=i.__iter__() #
print(i1)
# # <list_iterator object at 0x000000358B768A90>
# # <list_iterator object at 0x000000358B768A90> 迭代器也有iter方法,本身也是可迭代对象,除了iter还有next方法
# 列表是有序的 字典是无序的
print(next(i))
print(next(i))
print(next(i))
print(next(i))
print(next(i))
# print(next(i)) #StopIteration
# 依赖索引的适用于列表、元组、字符串,迭代器适用于所有可迭代的数据类型
7.4 迭代器 不依赖索引取值
# s='hello'
# l=['a','b','c','d','e']
# t=('a','b','c','d','e')
# dic={'name':'leo','sex':'male','age':28}
# set1={1,2,3,4,5}
# f=open('user.txt')
# 都是可迭代对象 都有__iter__这个方法
# s.__iter__()
# l.__iter__()
# t.__iter__()
# dic.__iter__()
# set1.__iter__()
# f.__iter__()
l=['a','b','c','d','e']
dic={'name':'leo','sex':'male','age':28}
iter_l=l.__iter__()
while True:
#print(next(iter_l)) #
try:
print(next(iter_l)) # iter_l.__next__()
except StopIteration: # 捕捉异常,写好异常的名字
break # 碰到这个异常 终止循环
iter_dict=dic.__iter__()
while True:
try:
k=next(iter_dict) ### 取得字典的key
print(k,dic[k]) ### 取字典的key和value
except StopIteration:
break
7.5 迭代器总结
### 文件迭代:
with open('a.txt',encoding='utf-8') as f:
# f.__iter__() # 可迭代对象
# f.__next__() # 迭代器对象 说明可以直接next
print(next(f))
print(next(f))
print(next(f))
# f.read() # 适用于较小文件
迭代器总结:
1、有_iter_ 可迭代对象
2、有_next_ 迭代器对象
迭代器对象的优点:
1、提供一种统一的(不依赖索引)迭代方式
2、迭代器本身,比起其他数据类型更省内存 自定义迭代器可以存无穷的值
迭代器对象的缺点:
1、一次性只能往后走next,不能回退,不如索引取值灵活
2、无法预知什么时候取值结束,即无法预知长度
# for循环原理:迭代器协议
l=['a','b','c','d','e']
for item in l: # iter_l=l._iter_() 只要有iter方法 都可以放在for循环后面
print(item) # next(iter_l) for循环会捕捉异常并结束循环
7.6 判断可迭代对象与迭代器对象(了解)
from collections import Iterable,Iterator
s='hello'
l=['a','b','c','d','e']
t=('a','b','c','d','e')
dic={'name':'leo','sex':'male','age':28}
set1={1,2,3,4,5}
f=open('user.txt')
print(isinstance(s,Iterable)) ### 可迭代对象
print(isinstance(s,Iterator)) ### 迭代器对象
print(isinstance(f,Iterable))
print(isinstance(f,Iterable)) ### 文件即是可迭代对象,也是迭代器对象
第8章 生成器
# 生成器:在函数内部包含yield关键字,那么该函数执行的结果是生成器
def func():
print('first')
yield 111
print('second')
yield 222
print('third')
yield 333
# func() # 含有yield关键字 代码并不会直接执行 而是得到了生成器
g=func()
print(g) # <generator object func at 0x0000006F9032FE60> generator 生成器
from collections import Iterable,Iterator
#g.__iter__
#g.__next__
print(isinstance(g,Iterable))
print(isinstance(g,Iterator))
True
True
### 生成器就是迭代器
def func():
print('first')
yield 111
print('second')
yield 222
print('third')
yield 333
g=func()
# next(g) # 要func函数执行 要使用next # 得到first, next会从头到尾执行函数,碰到yield 相当于retrun
print(next(g)) # 得到yield的值 next会触发迭代器的运行函数的执行,碰到yield停下来 并且将后面的值返回
>>> first
>>> 111
#1、把函数做成迭代器
#2、对比return,可以返回多次值,可以挂起/保存函数的运行状态
def func():
print('first')
yield 111
print('second')
yield 222
print('third')
yield 333
print('fourth')
# func() # 含有yield关键字 代码并不会直接执行 而是得到了生成器
g=func()
# print(g) # <generator object func at 0x0000006F9032FE60> generator 生成器
# from collections import Iterable,Iterator
#g.__iter__
#g.__next__
# print(isinstance(g,Iterable))
# print(isinstance(g,Iterator))
### 生成器就是迭代器
# next(g) # 要func函数执行 要使用next # 得到first, next会从头到尾执行函数,碰到yield 相当于retrun
print(next(g)) # 得到yield的值 next会触发迭代器的运行函数的执行,碰到yield停下来 并且将后面的值返回
print("=========")
print(next(g)) # yield帮忙暂停了函数的执行 下一次执行从暂停的位置继续
print("=========")
print(next(g))
print("=========")
print(next(g)) # 这一次没有yield 没有返回值了就报 StopIteration
def func():
print('first')
yield 111
print('second')
yield 222
print('third')
yield 333
print('fourth')
g=func()
for i in g: # i=iter(g) ### 函数也可以被循环 因为是迭代器 只要是迭代器对象就可以被for循环
print(i)
>>> first
>>> 111
>>> second
>>> 222
>>> third
>>> 333
>>> fourth
8.1 无穷值的类型
# 生成器
def func(n):
print('我开动了')
while True:
yield n
n+=1
g=func(0)
# print(next(g))
# print(next(g))
for i in g:
print(i)
8.2 使用生成器写range
# x=range(10000)
# # print(x) #range(0, 10000)
# print(x.__iter__()) # 可迭代对象
#
# for i in range(10000):
# print(i) # range得到的是可迭代对象 一次一个值 不要在python2里这么做
def my_range(start,stop):
while True:
if start == stop:
raise StopIteration
yield start
start+=1
for i in my_range(1,3):
print(i)
# g=my_range(1,3)
# print(next(g))
# print(next(g))
# print(next(g)) # StopAsyncIteration
8.3 使用生成器写tail-f|grep error
# tail -f a.txt | grep 'error'
# 管道符号 | 一个程序 传给 另外一个程序
import time
def tail(filepath):
with open(filepath,'r') as f:
f.seek(0,2)
while True:
line=f.readline()
if line:
yield line
else:
time.sleep(0.2)
def grep(patten,lines):
for line in lines:
if patten in line:
print(line,end='')
# lines=tail('access.log')
# for line in lines:
# print(line)
grep('error',tail('access.log')) # 只有error才会打印
### 文本追加内容
with open('access.log','a') as f:
f.write('1234567error\n')
第9章 三元表达式
# def foo(x):
# if x > 3:
# return 'ok'
# else:
# return 'no'
# x=10
res='ok' if x > 3 else 'no' # 判断条件在中间 成立的值在左边 不成立在右边
print(res)
def max2(x,y):
return x if x > y else y
# # if x > y:
# # return x
# # else:
# # return y
print(max(1,3))
name=input('>>: ')
# if name == 'alex':
# print('SB')
# else:
# print('NB')
res='SB' if name == 'alex' else 'NB'
print(res)
把最简单的if判断用一行来表达
第10章 列表解析
# # 10个鸡蛋列表
# l=[]
# for i in range(10):
# l.append('egg%s' %i)
# print(l)
# 列表解析
l=['egg%s' %i for i in range(10) ] # 会循环10次 产生的值会直接放在列表里去放到左边 当做第一个元素
print(l)
# 直接在列表里写for循环
# 10个鸡蛋列表 只要5个
l=[]
for i in range(10):
if i >=5:
l.append('egg%s' %i)
print(l)
# 列表解析
l=['egg%s' %i for i in range(10) if i >=5 ]
print(l)
# 新列表的值 是原来值的平方
# nums=[1,2,3,4,5,6]
# new_nums=[]
# for item in nums:
# new_nums.append(item**2)
# print(new_nums)
nums=[1,2,3,4,5,6]
new_nums=[item**2 for item in nums]
print(new_nums)
new_nums=[item**2 for item in nums if item > 3 ]
print(new_nums)
# 把有结尾含有sb的加入到一个新列表
names=['alex_sb','wupeiqi_sb','egon','yuanhao_sb']
new_names=[ i for i in names if i.endswith('sb')]
print(new_names)
第11章 生成器表达式
# 生成器表达式
# 和列表解析一样 把[]换成()
g=('egg%s' %i for i in range(10000)) # <generator object <genexpr> at 0x0000008A7DDFFF10> 生成器
print(g)
print(next(g)) # 一次取一个值
print(next(g))
数据量大的情况 就不用[],而用生成器
# 求文件中access.log 最长一行的内容的长度
with open('access.log','r',encoding='utf-8')as f:
# new_l=[len(line) for line in f]
# print(new_l)
# print(max(new_l)) # \n换行算一个字符
# 如果内容非常大 要用生成器
res=((len(line) for line in f))
print(max(res))
# 求a.txt中的购物花了多少钱
# print(sum([1,2,3])) # sum求和函数
# print(sum((i for i in range(3)))) # 0 + 1 + 2 sum计算生成器表达式
# 这样取出文件中每一行花的钱
# l=[]
# for line in f: # 循环读取文件内容
# goods=line.split() # 先按照空格切分 获取内容
# price=int(goods[1]) # 1 2 是商品价格和购买数量
# count=int(goods[2])
# cost=price * count # 计算一行的商品价格总和
# l.append(cost) # 加入新列表
# # print(l)
#
# print(sum(l)) # 计算列表之和 196060
# [{'name':'apple','price':333,'count':3}]
with open('a.txt','r',encoding='utf-8') as f:
# l=[ float(line.split()[1]) * int(line.split()[2]) for line in f ] # 列表解析 文件内容过大时使用()生成器表达式
# print(sum(l)) # 196060.0
# info= [{ 'name':line.split()[0],'price':float(line.split()[1]),'count':line.split()[2]} for line in f ]
# print(info) #[{'name': 'apple', 'price': 10.0, 'count': '3'},...]
# 取出价格大于等于30000
info = [{'name': line.split()[0], 'price': float(line.split()[1]), 'count': line.split()[2]} for line in f if float(line.split()[1]) >= 30000]
print(info) # [{'name': 'tesla', 'price': 100000.0, 'count': '1'}, {'name': 'lenovo', 'price': 30000.0, 'count': '3'}]
第12章 序列化