标签:协程函数、模块、包
第一:
1、协程函数:
yield 是把函数的结果作为一个生成器。
一个对象如果有iter和next方法,说明这个对象是一个迭代器、迭代器也是生成器。
如果一个对象只有iter方法,那么这个对象是一个可迭代的对象。
yield就是把函数的执行结果封装好iter和next方法、即可得到一个迭代器。
他的功能和return功能类似、都可以返回值、但是不同的是return只能返回一次值、而yield可以返回多次值。
函数暂停与运行的状态是又yield保存。
例1、
#yield
def func(count):
print(‘start‘)
while True:
yield count
count+=1
g=func(10)
print(g)
print(next(g))
print(next(g))
例2:
#yield的表达式应用。
def eater(name):
print(‘%s 说:我开动了‘ %name)
while True:
food=yield
print(‘%s eat %s‘ %(name,food))
res=eater(‘xz‘)
print(next(res))
print(‘================‘)
res1=next(res)
print(res1)
>>
xz 说:我开动了
None
================
xz eat None
Non
#yield的表达式、执行前必须先初始化、或者传值none
#yield的表达式应用。
def eater(name):
print(‘%s 说:我开动了‘ %name)
while True:
food=yield
print(‘%s 吃 %s‘ %(name,food))
res=eater(‘xz‘)
#第一阶段初始化,让生成器初始到一个位置
next(res)**next的目的就是给yield一个none值
#第二阶段、给yield传值
res.send(‘包子‘)
>>
xz 说:我开动了
xz 吃 包子
xz 吃 骨头
例3:
#yield的表达式应用。
def eater(name):
print(‘%s 说:我开动了‘ %name)
food_list=[]
while True:
food=yield food_list
print(‘%s 吃 %s‘ %(name,food))
food_list.append(food)
res=eater(‘xz‘)
#第一阶段初始化,让生成器初始到一个位置
# next(res)
res.send(None)
#第二阶段、给yield传值
print(res.send(‘包子‘))
print(res.send(‘菜汤‘))
>>
xz 说:我开动了
xz 吃 包子
[‘包子‘]
xz 吃 菜汤
[‘包子‘, ‘菜汤‘]
例4:
#yield的表达式应用。
def eater(name):
print(‘%s 说:我开动了‘ %name)
food_list=[]
while True:
food=yield food_list
print(‘%s 吃 %s‘ %(name,food))
food_list.append(food)
def func():
res=eater(‘xiaozhang‘)
next(res)
while True:
food_inp=input(‘>>‘).strip()
if not food_inp:continue
res1=res.send(food_inp)
print(res1)
func()
>>
xiaozhang 说:我开动了
>>菜汤
xiaozhang 吃 菜汤
[‘菜汤‘]
>>
#装饰器解决初始化的问题:
def init(func):
def warpper(*args,**kwargs):
res=func(*args,**kwargs)
next(res)
return res
return warpper
@init
def eater(name):
print(‘%s 说:我开动了‘ %name)
food_list=[]
while True:
food=yield food_list
print(‘%s 吃 %s‘ %(name,food))
food_list.append(food)
def func1():
res=eater(‘xiaozhang‘)
while True:
food_inp=input(‘>>‘).strip()
if not food_inp:continue
res1=res.send(food_inp)
print(res1)
func1()
2、面向过程:核心是过程二字、过程即解决问题的步骤。
基于面向过程去设计程序就像一条工业流水线、是一种机械式的思维。
优点:程序结构清晰、易读、流程化
缺点:可扩展性差、一条流程线只解决一个问题
应用场景:linux内核……、功能单一
例1:使用面向过程的方法、实现grep -lr ‘error‘ /dir/#显示文件中有error的列表文件
import os
def init(func):
def warpper(*args,**kwargs):
res=func(*args,**kwargs)
next(res)
return res
return warpper
第一阶段:找到文件的决定路径
@init
def search(target):
while True:
filepath=yield
g=os.walk(filepath)
for pardir,_,files in g:
for file in files:
abspath=r‘%s\%s‘ %(pardir,file)
target.send(abspath)
第二阶段:打开文件
@init
def opener(target):
while True:
abspath=yield
with open(abspath,‘rb‘) as f:
target.send((abspath,f))
第三阶段:循环读
@init
def cat(target):
while True:
abspath,f=yield
for line in f:
res=target.send((abspath,line))
if res:break
第四阶段:过滤
@init
def grep(patten,target):
tag=False
while True:
abspath,line=yield tag
tag = False
if patten in line:
target.send(abspath)
tag=True
第五阶段:打印该行属于的文件名
@init
def printer():
while True:
abspath=yield
print(abspath)
g = search(opener(cat(grep(‘error‘.encode(‘utf-8‘), printer()))))
g.send(r‘H:\test‘)
3、递归函数:
在一个函数的调用过程中、直接或者间接的调用了函数本身。
递归效率比较低。
#直接
def func():
print(‘from func‘)
func()
func()
#间接
def foo():
print(‘from foo‘)
bar()
def bar():
print(‘from bar‘)
foo()
foo()
#递归
def age(n):
if n == 1:
return 18
else:
return (age(n-1)+2)
print(age(5))
递归必须有一个明确的条件、python没有伪递归
#递归
l=[1,3,[11,33],[11,[12,23,[44]]]]
def search(l):
for item in l:
if type(item) is list:
search(item)
else:
print(item)
search(l)
#二分法
l = [1,2,7,7,10,31,44,47,56,99,102,130,240]
#怎么判断某一个数字是否在列表内?
def binary_search(l,num):
print(l)
if len(l) > 1:
mid_index=len(l)//2
if num > l[mid_index]:
l=l[mid_index:]
binary_search(l,num)
elif num < l[mid_index]:
l=l[:mid_index]
binary_search(l,num)
else:
print(‘find it‘)
else:
if l[0] == num:
print(‘find it‘)
else:
print(‘not exit‘)
return
binary_search(l,32)
第二、模块与包
1、模块就是包含一个了python定义和声明的文件、文件名就是模块名字加上py的后缀。
2、 模块被导入默认就是执行模块文件
3、导入模块干了那些事:
A、执行源文件
B、以原文件产生一个全局名称空间
C、在当前位置拿到一个模块名指向2创建的名称空间
4、from ....import
A、优点:形式上不用使用源文件内的名字时无需加前缀,使用方便
B、缺点:容易与当前文件的名称空间内的名字混淆。
C、横杠只是对*起作用。有隐藏作用、可以使用__all__=[] 控制*的范围。
5、模块的加载
A、模块只是在第一次导入的时候才会执行,之后都是直接引用内存中已经加载的。
import sys
print(sys.modules) #存放的是已经加载到内存的模块字典
模块的寻找顺序:
内存中==>内置模块==>sys.path
自定义的模块不能与py自带的模块重名。
一个py文件有2中用途、脚本和模块。
py文件当做脚本运行时:__name__等于__main__
py文件当做模块调用时:__name__等于模块名
包就是模块的另一种模式、包下面有一个_init_.py的文件夹,就是包。
但是在这仅仅是py2.x的定义,在py3.x中没有_init_.py文件的文件夹也是包。
B、无论是import还是from....import导入、只要遇到点(.)这都是包才有的导入语法、点的左面一定是一个包。
包即模块、导入包就是导入模块。
os模块:
os.path.abspath(__file__)#获取当前文件的绝对路径。
6、日志模块的参数:
filename:指创建filehandler
filemode:文件打开的方式:默认为a可以指定为w
format:值handle使用的日志显示格式。
datefmt:指定日期时间格式。
level:设置日志的级别
stream:用指定的stream创建streamHandler、
日志的格式:
%(name)s logger的名字、并非用户名
%(levelno)s 数字形式的日志级别
%(levelnames)s 文本形式的日志级别
%(pathname)s 调用日志输出函数的模块的完整路径、可能没有
%(filename)s 调用日志输出函数的模块的文件名
%(module)s 调用日志输出函数的模块名
%(funcName)s 调用日志输出函数的函数名
%(lineno)s 调用日志输出函数的语句所在代码行
%(created)f 当前时间、用UNIX的标准时间的浮点表示
%(relativeCreated)d 输出日志信息时、自logger创建以来的毫秒数
%(asctime)s 字符串形式的当前时间、默认格式是"2003-07-08 16:44:22,234"逗号后面的是毫秒
%(thread)d 线程ID、可能咩有
%(threadName)s 线程名、可能无
%(process)d 进程ID、可能无
%(message)s 用户输出的消息
6、python正则:
\w 匹配字母数字下及划线
\W 匹配非字母数字下划线
\s 匹配任意空白字符、等价于[\t\n\r\f]
\S 匹配任意非空字符
\d 匹配任意数字、等价于[0-9]
\D 匹配任意非数字
\A 匹配字符串开始
\Z 匹配字符串的结束、如果是存在换行、只匹配到换行钱的结束字符串。
\z 匹配字符串结束
\G 匹配最后匹配完成的位置
\n 匹配一个换行符
\t 匹配一个制表符
^ 匹配字符串的开头
$ 匹配字符串的结尾
. 匹配任意字符、除了换行符、当re.DOTALL标记被指定时、则可以匹配包括换行符的任意字符。
[..] 用来表示一组字符、单独列出[amk]、匹配a或者m或者k
[^..] 不在[]中的字符、[^123] 匹配除了123之外的数字
* 匹配0个或者多个表达式
+ 匹配一次或者多次表达式
? 匹配0次或者1次表达式
{n} 匹配n次表达式
{n,m} 匹配n次到m次表达式
a|b 匹配a或者b
() 匹配括号内的表达式、也表示一个组。
本文出自 “男儿该自强” 博客,请务必保留此出处http://nrgzq.blog.51cto.com/11885040/1953216
标签:协程函数、模块、包
原文地址:http://nrgzq.blog.51cto.com/11885040/1953216