Python自动化开发课堂笔记【Day04】 - Python基础(函数补充,模块,包)

表达式形式的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:\Users\Administrator\PycharmProjects\python17期\day5\a‘
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), ‘\n‘, 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)ome\s‘, 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*oo\w*‘, 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*oo\w*‘)
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那必须使用后者。

时间: 2024-10-12 13:24:39

Python自动化开发课堂笔记【Day04】 - Python基础(函数补充,模块,包)的相关文章

Python自动化开发课堂笔记【Day04】 - Python基础(函数)

函数对象 函数是第一类对象,即函数可以当作数据传递.具体用法分成以下四类: 1. 可以被引用 1 def foo(): 2 print('from foo') 3 func=foo 4 print(foo) ---> <function foo at 0x00386C48> --> foo函数在内存中地址 5 print(func) ---> <function foo at 0x00386C48> 6 foo() ---> from foo 7 func(

Python自动化开发课堂笔记【Day15】- Django基础

WEB框架 框架,即framework,特指为解决一个开放性问题而设计的具有一定约束性的支撑结构,使用框架可以帮你快速开发特定的系统,简单地说,就是你用别人搭建好的舞台来做表演. 对于所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端. 最简单的Web应用就是先把HTML用文件保存好,用一个现成的HTTP服务器软件,接收用户请求,从文件中读取HTML,返回. 如果要动态生成HTML,就需要把上述步骤自己来实现.不过,接受HTTP请求.解析HTTP请

Python自动化开发课堂笔记【Day06】 - Python基础(模块)

正则模块 常用正则表达式列表(盗图一张:-P) 1 import re 2 3 print(re.findall('\w','abc123d_ef * | - =')) 4 print(re.findall('\W','abc123d_ef * | - =')) 5 print(re.findall('\s','abc1\n23\td_ef * | - =')) 6 print(re.findall('\S','abc1\n23\td_ef * | - =')) 7 print(re.finda

Python自动化开发课堂笔记【Day03】 - Python基础(字符编码使用,文件处理,函数)

字符编码使用 1. 文本编辑器如何存取文件 文本编辑器相当一个运行在内存中的进程,所以文件内容在编辑未存储时都是在内存中的,尚未存储在硬盘之中,在没有保存之前,所编辑的任何文本都只是一堆字符,没有任何逻辑上的意义,当存储文件的时候需要以一定的编码格式存储于硬盘之中,当进行文件读取的时候也需要以同样的编码格式进行读取到内存之中进行操作,如果存储文件的编码和读取文件的编码不一致则会引起读取过程中的乱码导致文件操作失败. P.S. --> Python解释器执行py文件的原理. Step1. Pyth

Python自动化开发课堂笔记【Day06】 - Python进阶(类)

类与对象 面向过程的程序设计: 优点:极大的降低了程序的复杂度 缺点:一套流水线或者流程就是用来解决一个问题,生产汽水的流水线无法生产汽车,即使能,也是得大改,改一个组件,牵一发而动全身面向对象的程序设计 优点:解决了程序的扩展性,对于某一个对象单独修改,会立刻反映到整个体系中,如对游戏中一个人物参数的特征和技能修改都很容易 缺点:可控性差,无法像面向过程的程序设计流水线式的可以很精准的预测问题的处理流程和结果,面向对象的程序一旦开始就由对象之间的交互解决问题,谁也无法预测最终结果. pytho

Python自动化开发课堂笔记【Day07】 - Python进阶(类)- 02

类与对象 对象是特征(变量)与技能(函数)的结合体,类是一系列对象共有的特征与技能的结合体 现实生活中:先有对象,再总结归纳出类 程序中:一定是先定义类,再实例化出对象定义类的语法:class 类名: '''注释''' 类体(可以是任意代码) 1 class Chinese: 2 country = 'China' 3 def __init__(self,name,age): 4 self.name = name 5 self.age = age 6 print('--->',self.name

Python自动化开发课堂笔记【Day14】 - Java Script

JavaScript的基础 1. JS的引入方式 1 直接编写 <script> alert('hello yuan') </script> 2 导入文件 <script src="hello.js"></script> 2. JS的变量.常量和标识符 a. JS的变量 如何在JS中定义使用变量 1.声明变量时不用声明变量类型. 全都使用var关键字; var a;<br>a=3; 2.一行可以声明多个变量.并且可以是不同类型

Python自动化开发课堂笔记【Day15】- jQuery

jQuery 1. jQuery是继prototype之后又一个优秀的Javascript框架.其宗旨是--WRITE LESS,DO MORE! 2. 它是轻量级的js库(压缩后只有21k) ,这是其它的js库所不及的,它兼容CSS3,还兼容各种浏览器 3. jQuery是一个快速的,简洁的javaScript库,使用户能更方便地处理HTMLdocuments.events.实现动画效果,并且方便地为网站提供AJAX交互. 4. jQuery还有一个比较大的优势是,它的文档说明很全,而且各种应

Python自动化开发课堂笔记【Day08】 - Python进阶(面向对象的高级用法,网络编程)

面向对象的高级用法 1. __str__ 只要执行打印对象的操作,就会触发该对象类中的__str__方法(也就是对象的绑定方法)它是一种默认的方法,默认的打印输出为<__main__.Foo object at 0x003EE350>,但是如果将该绑定方法在类中重写的话,要求必须有以字符串类型的返回值,返回形式可以自己设定. class Foo: def __init__(self,name,age): self.name = name self.age = age def __str__(s