zoukankan      html  css  js  c++  java
  • Python自动化开发课堂笔记【Day05】

    表达式形式的yield

    yield的语句形式: yield 1
    yield的表达式形式: x=yield

    1 x=yield
    2 g.send('1111') #先把1111传给yield,由yield赋值给x,然后再往下执行,直到再次碰到yield,然后把yield后的返回值返回

    协程函数示例

     1 def gen(func):
     2     def wrapper(*args,**kwargs):
     3         res = func(*args,**kwargs)
     4         next(res) #相当于next(g)或者g.send(None)
     5         return res
     6     return wrapper
     7 
     8 @gen
     9 def eater(name):
    10     print('%s start to eat' % name)
    11     food_list = []
    12     while True:
    13         food = yield food_list|
    14         food_list.append(food)
    15         print('%s start to eat %s'% (name,food))
    16 
    17 g = eater('Albert') #初始化操作,由装饰函数gen对eater函数进行初始化,传入一个空值
    18 print(g.send('Apple')) #此时函数挂起在红线出,send执行后,将Apple传给yield,并有yield赋值给food,之后再执行append操作,让后返回food_list
    19 print(g.send('Peach'))

    模拟 grep -rl 'python' /root 示例

     1 import os
     2 
     3 def init(func):
     4     def wrapper(*args,**kwargs):
     5         res = func(*args,**kwargs)
     6         next(res)
     7         return res
     8     return wrapper
     9 
    10 @init
    11 def search_dir(target):
    12     while True:
    13         search_path = yield #将搜索路径赋值给search_path
    14         g = os.walk(search_path)#遍历目录下的所有文件夹和子文件夹以及各文件夹下面的文件
    15         for par_dir, _, files in g: #遍历列表g中所有的父级文件夹目录和文件
    16             for file in files:#遍历文件夹下所有文件
    17                 file_abs_path = r'%s\%s', (par_dir, file)#形成绝对路径字符串
    18                 target.send(file_abs_path)#将文件绝对路径传值给open_file函数
    19 @init
    20 def open_file(target):
    21     while True:
    22         file_abs_path = yield #将文件绝对路径赋值给file_abs_path
    23         with open(file_abs_path,'r', encoding='urf-8') as f:
    24             target.send((f,file_abs_path))#将文件内容和绝对路径传值给cat_file函数
    25 @init
    26 def cat_file(target):
    27     while True:
    28         f, file_abs_path = yield #将yield中文件内容和绝对路径赋值
    29         for line in f:#逐行遍历文件内容
    30             tag = target.send(line, file_abs_path)#将每行内容和绝对路径传值给grep_line函数进行判断,并返回值tag
    31             if tag: #如果返回值tag为True,就停止对该文件剩余行数的遍历,并进行下一文件逐行遍历
    32                 break
    33 
    34 @init
    35 def grep_line(target,pattern):
    36     tag = False
    37     while True:
    38         line, file_abs_path = yield tag #将每行内容和绝对路径赋值,并取到返回值tag
    39         tag = False #初始化tag
    40         if pattern in line:#如果改行内容匹配到目标字符串,返回值tag为True
    41             tag = True
    42             target.send(file_abs_path)  #将文件绝对路径传值给print函数打印
    43 @init
    44 def print_file():
    45     file_abs_path = yield
    46     print(file_abs_path)
    47 
    48 x = r'C:UsersAdministratorPycharmProjectspython17期day5a'
    49 g = search_dir(open_file(cat_file(grep_line(print_file(), 'python'))))
    50 print(g)
    51 g.send(x)

    面向过程的程序设计:是一种流水线式的编程思路,是机械式
      优点:
        程序的结构清晰,可以把复杂的问题简单
      缺点:
        扩展性差
      应用场景:
        linux内核,git,httpd

    匿名函数 

    匿名函数:用之则弃的函数,基本不会占用内存,不像正常的全局函数,会存活到程序结束

    1 def func(x,y):
    2     return x+y
    3 func(1,2)
    4 
    5 f=lambda x,y:x+y
    6 print(f)
    7 print(f(1,2))

    内置函数补充

      1. max,min,zip,sorted的用法, 运用到匿名函数的概念

     1 salaries={
     2 'egon':3000,
     3 'alex':100000000,
     4 'wupeiqi':10000,
     5 'yuanhao':2000
     6 }
     7 for i in salaries:
     8     print(i)
     9 print(max(salaries))
    10 res=zip(salaries.values(),salaries.keys())
    11 
    12 print(list(res))
    13 print(max(res))
    14 
    15 def func(k):
    16     return salaries[k]
    17 
    18 print(max(salaries,key=func))
    19 print(max(salaries,key=lambda k:salaries[k]))
    20 print(min(salaries,key=lambda k:salaries[k]))
    21 
    22 print(sorted(salaries)) #默认的排序结果是从小到到
    23 print(sorted(salaries,key=lambda x:salaries[x])) #默认的排序结果是从小到到
    24 print(sorted(salaries,key=lambda x:salaries[x],reverse=True)) #默认的排序结果是从小到到
    2. map,reduce,filter函数
     1 l=['alex','wupeiqi','yuanhao']
     2 res=map(lambda x:x+'_SB',l)
     3 print(res)
     4 print(list(res))
     5 
     6 nums=(2,4,9,10)
     7 res1=map(lambda x:x**2,nums)
     8 print(list(res1))
     9 
    10 from functools import reduce
    11 l=[1,2,3,4,5]
    12 print(reduce(lambda x,y:x+y,l,10))
    13 
    14 l=['alex_SB','wupeiqi_SB','yuanhao_SB','egon']
    15 res=filter(lambda x:x.endswith('SB'),l)
    16 print(list(res))

    递归调用

      1. 定义:在函数调用过程中,直接或间接地调用了函数本身,这就是函数的递归调用

    2. 递归效率低,需要在进入下一次递归时保留当前的状态,解决方法是尾递归,但是Python没有,且对递归层级做了限制
      1.必须有一个明确的结束条件
      2.每次进入更深一层递归时,问题规模相比上次递归都应有所减少
      3.递归效率不高,递归层次过多会导致栈溢出。

    1 import sys
    2 print(sys.getrecursionlimit()) #查看Python可以递归的层数,默认1000,可设置
    3 print(sys.setrecursionlimit(1000000)) #设置Pyth可递归层数。最高8000
    4 print(sys.getrecursionlimit()) #查看设置结果

      3. 递归的原理

     1 age(5)=age(4)+2
     2 age(4)=age(3)+2
     3 age(3)=age(2)+2
     4 age(2)=age(1)+2
     5 age(1)=18
     6 
     7 age(n)=age(n-1)+2 #n>2
     8 age(n)=18         #n=1 
     9 
    10 def age(n):
    11     if n == 1:
    12         return 18
    13     return age(n-1)+2
    14 print(age(5))

      4. 递归的应用(二分法)

     1 第一种方式:
     2 raw_lst = [1,5,324,12,67,34,32,879,65,23,4,78,56,2,6,8]
     3 while True:
     4     lst = sorted(raw_lst)
     5     t_num = input('>>>: ')
     6     n = int(t_num)
     7     while True:
     8         if len(lst) // 2 == 0:
     9             print('Nothing found')
    10             break
    11         elif lst[len(lst) // 2] == n:
    12             print('Bingo')
    13             break
    14         elif lst[len(lst) // 2] > n:
    15             lst = lst[:len(lst) // 2]
    16         elif lst[len(lst) // 2] < n:
    17             lst = lst[len(lst) // 2:]
    18 
    19 第二种方式:
    20 raw_list = [1, 2, 10,33,53,71,73,75,77,85,101,201,202,999,11111]
    21 def search_num(target_num, seq):
    22     seq = sorted(seq) # 如果列表是无序的情况下需要先进性排序
    23     if len(seq) == 0:
    24         return 'Not found...'
    25     mid_index = len(seq)//2
    26     mid_num = seq[mid_index]
    27     if mid_num > target_num:
    28         seq = seq[:mid_index]
    29         search_num(target_num, seq)
    30     elif mid_num < target_num:
    31         seq = seq[mid_index+1:]
    32         search_num(target_num, seq)
    33     elif mid_num == target_num:
    34         print('Bingo!!!')
    35 search_num(33,raw_list)

    模块

    1. 什么是模块
      一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀
    2. 为什么要使用模块
      程序中定义的函数或者变量都会因为python解释器的关闭而丢失,因此通常我们会将程序以文件的方式保存下来方便重复利用。
      为了方便管理越来越多的文件,我们将这些文件归纳为模块,实用的时候就把模块导入到程序中
    3. 如何使用模块

     1 # spam模块文件
     2 # -*- coding:utf-8 -*-
     3 # !/usr/bin/python
     4 __all__ = ['money','read1'] #from spam import * 导入的所有变量,类表中只添加所需变量
     5 money = 1000
     6 def read1():
     7     print('spam->read1->money',money)
     8 def read2():
     9     print('spam->read2 calling read1')
    10     read1()
    11 def change():
    12     global money
    13     money = 0
    14 #spam.py当作脚本执行时,__name__=='__main__'
    15 #spam.py当作模块导入时,__name__=='模块名'
    16 # print('当前文件的用途是:', __name__)
    17 #作用:用于判断当前文件时按照脚本执行还是模块执行
    18 if __name__ == '__main__':
    19     print('from the spam.py')
    20     print('当作脚本执行')
    21     change()
    22     print(money)
     1 import...导入模块进行的操作:
     2 1. 产生新的名称空间
     3 2. 以新建的名称空间为全局名称空间,执行文件的代码
     4 3. 拿到一个模块名spam,指向spam.py产生的名称空间
     5     
     6 # fortest.py文件
     7 # -*- coding:utf-8 -*-
     8 # !/usr/bin/python
     9 import spam as x #起一个别名作为引用
    10 import spam
    11 money = 2000 #此money并非spam名称空间中的money
    12 print(spam.money) #从spam的名称空间中的money变量值
    13 print(x.money) #相同效果
    14 spam.read1()
    15 spam.read2()
    16 spam.change() #修改spam空间中的money变量,任然以spam名称空间定义的为准
    17 print(spam.money)
    18 
    19 from...import...导入模块进行的操作:
    20 1. 产生新的名称空间
    21 2. 以新建的名称空间为全局名称空间,执行文件的代码
    22 3. 直接拿到就是spam.py产生的名称空间的名字
    23 
    24 优点:方便,不用加前缀
    25 缺点: 容易跟当前文件的名称空间冲突
    26 
    27 from spam import * #将spam中所有内容导入,使用时不用加前缀,慎用,容易和当前名称空间中变量发生冲突
    28 可以在模块文件中使用__all__=[]的方法来加以控制所需导入的名称
    29 
    30 # fortest.py文件
    31 # -*- coding:utf-8 -*-
    32 # !/usr/bin/python
    33 from spam import read1,money,read2,change
    34 print(money)
    35 read1()
    36 money = 10 #从spam取到的money的值已经被重新绑定赋值,但是spam中的money值没有改变
    37 print(money)
    38 def read1():
    39     print('===> from fortest.py read1')
    40 read1() #使用当前名称空间中函数定义的功能
    41 read2() #与导入方式无关,此函数从哪个名称空间导入,就会任然沿用该空间函数功能,所以调用的仍然是spam中的read1函数

    模块搜索路径

    顺序:内存空间 -> 内置函数 -> sys.path(从当前路径开始查找)
    import sys
    print(sys.path) #查看系统路径
    如果需要添加的模块和当前文件不在同一个目录中,那么需要将模块的路径添加到sys.path中,才能添加成功
    或者将该模块文件添加到site-package文件夹中

    re模块

      re.match:尝试从字符串的开始匹配一个模式,如:下面的例子匹配第一个单词。 

    re.match的函数原型为:re.match(pattern, string, flags)

    第一个参数是正则表达式,这里为"(w+)s",如果匹配成功,则返回一个Match,否则返回一个None;

    第二个参数表示要匹配的字符串;

    第三个参数是标致位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。

    1 import re
    2 text = "JGood is a handsome boy, he is cool, clever, and so on..."
    3 m = re.match(r"(w+)s", text)
    4 if m:
    5 print m.group(0), '
    ', m.group(1)
    6 else:
    7 print 'not match'  

      re.search:会在字符串内查找模式匹配,只到找到第一个匹配然后返回,如果字符串没有匹配,则返回None。

    re.search的函数原型为: re.search(pattern, string, flags)

    每个参数的含意与re.match一样。 

    re.match与re.search的区别:re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,直到找到一个匹配。

    1 import re
    2 text = "JGood is a handsome boy, he is cool, clever, and so on..."
    3 m = re.search(r'shan(ds)omes', text)
    4 if m:
    5 print m.group(0), m.group(1)
    6 else:
    7 print 'not search'  

    re.sub: 用于替换字符串中的匹配项。下面一个例子将字符串中的空格 ' ' 替换成 '-' :  

     re.sub的函数原型为:re.sub(pattern, repl, string, count)

    其中第二个函数是替换后的字符串;本例中为'-'

    第四个参数指替换个数。默认为0,表示每个匹配项都替换。

    re.sub还允许使用函数对匹配项的替换进行复杂的处理。如:re.sub(r's', lambda m: '[' + m.group(0) + ']', text, 0);将字符串中的空格' '替换为'[ ]'。

    1 import re
    2 text = "JGood is a handsome boy, he is cool, clever, and so on..."
    3 print re.sub(r's+', '-', text) 

    re.split: 可以使用re.split来分割字符串,如:re.split(r's+', text);将字符串按空格分割成一个单词列表。

    re.findall: 可以获取字符串中所有匹配的字符串。如:re.findall(r'w*oow*', text);获取字符串中,包含'oo'的所有单词。

    re.compile: 把正则表达式编译成一个正则表达式对象。可以把那些经常使用的正则表达式编译成正则表达式对象,这样可提高一定的效率。下面是一个正则表达式对象的一个例子:

    1 import re
    2 text = "JGood is a handsome boy, he is cool, clever, and so on..."
    3 regex = re.compile(r'w*oow*')
    4 print regex.findall(text)   #查找所有包含'oo'的单词
    5 print regex.sub(lambda m: '[' + m.group(0) + ']', text) #将字符串中含有'oo'的单词用[]括起来。

    从目录级别来组织模块的,也是通过import引入
      1. 无论是import形式还是from...import形式,凡是在导入语句中(而不是在使用时)遇到带点的,都要第一时间提高警觉:这是关于包才有的导入语法。
      2. 包是目录级的(文件夹级),文件夹是用来组成py文件(包的本质就是一个包含__init__.py文件的目录)
      3. import导入文件时,产生名称空间中的名字来源于文件,import包,产生的名称空间的名字同样来源于文件,即包下的__init__.py,导入包本质就是在导入该文件
    注意事项:
      1. 关于包相关的导入语句也分为import和from ... import ...两种,但是无论哪种,无论在什么位置,在导入时都必须遵循一个原则:
          凡是在导入时带点的,点的左边都必须是一个包,否则非法。可以带有一连串的点,如item.subitem.subsubitem,但都必须遵循这个原则。
      2. 对于导入后,在使用时就没有这种限制了,点的左边可以是包,模块,函数,类(它们都可以用点的方式调用自己的属性)。
      3. .对比import item 和from item import name的应用场景:如果我们想直接使用name那必须使用后者。

  • 相关阅读:
    拍照
    【HDU 4372】 Count the Buildings (第一类斯特林数)
    【HDU 5370】 Tree Maker(卡特兰数+dp)
    【HDU 4436】 str2int (广义SAM)
    【BZOJ 3926】 [Zjoi2015]诸神眷顾的幻想乡 (广义SAM)
    【HDU 5184】 Brackets (卡特兰数)
    【HDU 1133】 Buy the Ticket (卡特兰数)
    【BZOJ 1191】 [Apio2010]特别行动队 (斜率优化)
    【BZOJ 1597】 [Usaco2008 Mar]土地购买 (斜率优化)
    【BZOJ 1096】 [ZJOI2007]仓库建设 (斜率优化)
  • 原文地址:https://www.cnblogs.com/paodanke/p/6930612.html
Copyright © 2011-2022 走看看