• Python全栈开发,Day5


    本章内容

    1. 迭代器&生成器
    2. 装饰器
    3. 递归
    4. 算法基础
    5. 正则表达式
    6. 模块初识

    一、迭代器&生成器

    迭代器:

    迭代器是访问元素的一种方式。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退,不过这也没什么,因为人们很少在迭代途中往后退。另外,迭代器的一大邮电是不要求实现准备好整个迭代过程中所有的元素。迭代器仅仅在迭代到某个元素时才计算该元素,而在这之前或之后,元素可以不存在后者被销毁。这个特点使得它特别使用于遍历一些巨大或是无限的集合,比如几个G的文件

    特点:

    1. 访问者不需要关心迭代器内部的结构,仅需通过next()方法不断去取下一个内容
    2. 不能随机访问集合中的某个值,只能从头到尾依次访问
    3. 访问到一半时不能往回退
    4. 便于循环比较大的数据集合,节省内存

    生成一个迭代器:

     

     1 a = iter([1,2,3,4,5,6])
     2 print(a.__next__())
     3 print(a.__next__())
     4 print(a.__next__())
     5 print(a.__next__())
     6 print(a.__next__())
     7 
     8 
     9 结果:
    10 1
    11 2
    12 3
    13 4
    14 5

     

    生成generator

    定义:一个函数调用时返回一个迭代器,那这个函数就叫做生成器(generator),如果函数中包含yield语法,那这个函数就会编程生成器

    如下:

     1 def cash_out(amount):
     2     while amount>0:
     3         amount -= 1
     4         yield amount   #print amount
     5 
     6 ATM = cash_out(5)
     7 
     8 print("取到钱%s万"%ATM.__next__())
     9 print("花掉花掉!")
    10 print("取到钱%s万"%ATM.__next__())
    11 print("取到钱%s万"%ATM.__next__())
    12 print("花掉花掉")
    13 print("取到钱%s万"%ATM.__next__())
    14 print("取到钱%s万"%ATM.__next__())

    作用:

    这个yield的主要效果呢,就是可以使函数中断,并保存中断状态,中断后吗,代码可以继续往下执行,过一段时间还可以再重新调用这个函数,从上次yield的下一句开始执行。

    另外,还可以通过yield实现单线程的情况下实现并发运算的效果:

     1 import time
     2 
     3 def consumer(name):
     4     print("%s 准备吃包子啦!" % name)
     5     while True:
     6         baozi = yield
     7         print("包子[%s]来了,被[%s]吃了!" % (baozi, name))
     8 
     9 def producer(name):
    10     c = consumer('A')
    11     c2 = consumer('B')
    12     c.__next__()
    13     c2.__next__()
    14     print("老子开始准备做包子啦!")
    15     for i in range(10):
    16         time.sleep(1)
    17         print("做了2个包子!")
    18         c.send(i)
    19         c2.send(i)
    20 
    21 producer("alex")

    二、装饰器

     写代码要遵循开发封闭原则,虽然在这个原则是用的面向对象开发的,但是也适用于函数式编程,简单来说,它规定已经实现的功能代码不允许被修改,但可以被扩展,即:

    • 封闭:已实现的功能代码块
    • 开放:对扩展开发

    先来看一个例子: 1 import time

     2 def timmer(func):
     3     def deco(*args,**kwargs):
     4         start_time= time.time()
     5         time.sleep(2)
     6         func(*args,**kwargs)
     7         stop_time =time.time()
     8         print("the run time %s"%(stop_time-start_time))
     9     return deco
    10 
    11 @timmer
    12 def text1(oooo):
    13     print("in the text1",oooo)
    14 
    15 @timmer
    16 def text2(name,age,job,like):
    17     print("in the text2",name,age,job,like)
    18 text1('time')
    19 text2('Lyon',21,'it','dancing')
      输出如下:

    in the text1 nimade
    the run time 2.020908832550049
    in the text2 Lyon 21 it dancing
    the run time 2.014737844467163

     

    上述例子中,*args, **kwargs为非固定参数,而@timmer就是重头戏,由输出结果我们可以发现,text1和text2函数都有了timmer函数里面定义的功能,而且是在不改变源代码的条件下添加功能,这就是装饰器的作用。

    再看看下面的应用:

     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 # Author:Lyon
     4 import time
     5 user,passwd = 'Lyon','yangyong'
     6 def auth(auth_type):
     7     print("auth func:",auth_type)
     8     def outer_wrapper(func):
     9         def wrapper(*args, **kwargs):
    10             print("wrapper func args:", *args, **kwargs)
    11             if auth_type == "local":
    12                 username = input("Username:").strip()
    13                 password = input("Password:").strip()
    14                 if user == username and passwd == password:
    15                     print("33[32;1mUser has passed authentication33[0m")
    16                     res = func(*args, **kwargs)  # from home
    17                     print("---after authenticaion ")
    18                     return res
    19                 else:
    20                     exit("33[31;1mInvalid username or password33[0m")
    21             elif auth_type == "ldap":
    22                 print("搞毛线ldap,不会。。。。")
    23 
    24         return wrapper
    25     return outer_wrapper
    26 
    27 def index():
    28     print("welcome to index page")
    29 @auth(auth_type="local") # home = wrapper()
    30 def home():
    31     print("welcome to home  page")
    32     return "from home"
    33 
    34 @auth(auth_type="ldap")
    35 def bbs():
    36     print("welcome to bbs  page")
    37 
    38 index()
    39 print(home()) #wrapper()
    40 bbs()
    简单bbs相关

     

    有没有体会到装饰器的强大?

    更多内容请看http://www.cnblogs.com/wupeiqi/articles/4980620.html  

    三、递归

    特点:

    递归算法是一种直接后者简介地调用自身算法的过程。在计算机编写程序中,递归算法对解决一大类问题是十分有效的,它往往使算法的描述简介而且易于理解。

    递归算法解决问题的特点:

    1. 递归就是在过程或函数里调用自身。
    2. 在使用递归策略时,必须有一个明确的递归结束条件,称为递归出口。
    3. 递归算法解题通常显得很简洁,但递归算法解题的运行效率较低。所以一般不提倡用递归算法设计程序。
    4. 在递归调用的过程中系统为每一层的返回点、局部量等开辟了栈来存储。递归次数过多容易造成栈溢出等。所以一般不提倡用递归算法设计程序。

    要求:

    递归算法所体现的“重复”一般有按个要求:

    1. 每次调用在规模上都有所缩小(通常是减半);
    2. 相邻两次重复之间有紧密的联系,前一次要为后一次做准备(通常前一次的输出就作为后一次的输入);
    3. 在问题的规模极小时必须用直接给出解答而不再进行递归调用,因而每次递归调用都是有条件的(以规模未达到直接解答的大小为条件),无条件递归调用将会成为死循环而不能正常结束。

     

    实现

    例:

    • 通过递归实现2分查找

      现有列表primes = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97],要求用最快的方式找出23。请Low B,Low2B, LOW3B三个同学来回答这个问题。

      Low B:这个很简单,直接用if 23 in primes:print(“found it!”),语音未落就被老师打了,让你自己实现,不是让你用现成提供的功能,Low B于是说,那只能从头开始一个个数了,然后Low B被开除了。。

      Low 2B:因为这个列表是有序的,我可以把列表从中截取一半,大概如下:

          P1 = [2,3,5,7,11,13,17,19,23,29,31,37,41]

          P2 = [43,47,53,59,61,67,73,79,83,89,97]

          然后看P1[-1]也就是41是否比23大,如果比23大就代表23肯定在P1里面,否则那就肯定在P2里面。现在我们知道23比41小,所以23肯定在P1里面,但P1里依然有很多元素,怎么找到23呢?很简单,依然按上一次的方法,把P1分成2部分,如下:

          P1_a = [2,3,5,7,11,13,17]

          P1_b = [19,23 ,29,31,37,41]

          然后我们发现,23比P1_a最后一个值17大,那代表23肯定在P1_b中,P1_b中依然有很多元素,那就按之前的方法继续分半,最终用不了几次,肯定就把23找出来了!

      老师:很好,确实较Low B的方案强很多。然后转头问Low 3B,你有更好的想法么?

      Low 3B:啊。。。噢,我。。。我跟Low 2B的想法一样,结果被他说了。

      老师:噢,那你帮我把代码写出来吧。

      Low 3B此时冷汗直冒,因为他根本没思路,但还是硬着头皮去写了。。。。虽然自己没思路,但是会谷歌呀,三个小时过去了,终于憋出了一下代码:

     1 def binary_search(data_list,find_num):
     2     mid_pos = int(len(data_list) /2 ) #find the middle position of the list
     3     mid_val = data_list[mid_pos] # get the value by it's position
     4     print(data_list)
     5     if len(data_list) >1:
     6         if mid_val > find_num: # means the find_num is in left hand of mid_val
     7             print("[%s] should be in left of [%s]" %(find_num,mid_val))
     8             binary_search(data_list[:mid_pos],find_num)
     9         elif mid_val < find_num: # means the find_num is in the right hand of mid_val
    10             print("[%s] should be in right of [%s]" %(find_num,mid_val))
    11             binary_search(data_list[mid_pos:],find_num)
    12         else: # means the mid_val == find_num
    13             print("Find ", find_num)
    14  
    15     else:
    16         print("cannot find [%s] in data_list" %find_num)
    17  
    18 if __name__ == '__main__':
    19     primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
    20     binary_search(primes,67)
    View Code

      所以以上就是典型的递归的用法,程序里自己调用自己。

     四、算法基础

    • 冒泡排序

      将一个不规则的数组按从小到大的顺序进行排序

     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 # Author:Lyon
     4 
     5 data = [10,4,33,21,54,3,8,11,5,22,2,1,17,13,6]
     6 print("before sort:",data)
     7 previous = data[0]
     8 for i in range(len(data)):
     9     tmp = 0
    10     for j in range(len(data)-1):
    11         if data[j]>data[j+1]:
    12             tmp = data[j]
    13             data[j]=data[j+1]
    14             data[j+1]=tmp
    15 
    16     print(data)
    •  时间复杂度

    (1)时间频度

    一个算法执行所耗费的时间,从理论上是不能算出来的,必须上机运行测试才能知道。但我们不可能也没有必要对每个算法都上机测试,只需知道哪个算法花费的时间多,哪个算法花费的时间少就可以了。并且一个人算法花费的时间与算法中语句的执行次数成成正比例,哪个算法中语句执行次数多,它花费时间就多。一个算法中的语句执行次数称为语句频度或时间频度。记为T(n)。

    (2)时间复杂度

    在刚才提到的时间频度中,n称为问题的规模,当n不断变化时,时间频度T(n)也会不断变化。但有时我们想知道它变化时呈现什么规律。为此,我们引入时间复杂度概念。一般情况下,算法中基本操作重复执行的次数是问题规模n的某个函数,用T(n)表示,若有某个辅助函数f(n),使得当n趋近于无穷大时,T(n)/f(n)的极限值为不等于零的常数,则称f(n)是T(n)的同数量级函数。记作T(n)=O(f(n)),称O(f(n))为算法的渐进时间复杂度,简称时间复杂度。

    • 指数时间

    指的是一个问题求解所需要的计算时间m(n),依输入数据的大小n而呈指数成长(即输入数据的数量依线性成长,所花的时间将会以指数成长)

    1 for (i=1; i<=n; i++)
    2        x++;
    3 for (i=1; i<=n; i++)
    4      for (j=1; j<=n; j++)
    5           x++;

     

    第一个for循环的时间复杂度为O(n),第二个for循环的时间复杂度为O(n*n),则整个算法的时间复杂度为O(n+n*n)=O(n*N)。

    • 常数时间

    若对于一个算法,T(n)的上界与输入大小无关,则称其具有常数时间,记作O(1)时间。一个例子是访问数组中的单个元素,因为访问它只需要一条指令。但是,找到无序数组中的最小元素则不是,因为这需要遍历所有元素来找出最小值。这是一项线性时间的操作,或称O(n)时间。但如果预先知道元素的数量并假设数量保持不变,则该操作也可以被称为具有常数时间。

    • 对数时间

    若算法的T(n) = O(log n),则称其具有对数时间,常见的具有对数时间的算法有二叉树的相关操作和二分搜索。对数时间的算法是非常有效的,因为每增加一个输入,其所需要的额外计算时间会变小。递归地将字符串砍半并且输出是这个类别函数的一个简单例子。它需要O(log n)的时间因为每次输出之前我们都将字符串砍半。 这意味着,如果我们想增加输出的次数,我们需要将字符串长度加倍。

     

    • 线性时间 

    如果一个算法的时间复杂度为O(n),则称这个算法具有线性时间,或O(n)时间。非正式地说,这意味着对于足够大的输入,运行时间增加的大小与输入成线性关系。例如,一个计算列表所有元素的和的程序,需要的时间与列表的长度成正比。

    五、正则表达式

    语法:

    1 import re #导入模块名
    2  
    3 p = re.compile("^[0-9]")  #生成要匹配的正则对象 , ^代表从开头匹配,[0-9]代表匹配0至9的任意一个数字, 所以这里的意思是对传进来的字符串进行匹配,如果这个字符串的开头第一个字符是数字,就代表匹配上了
    4  
    5 m = p.match('14534Abc')  
    6  #按上面生成的正则对象 去匹配 字符串, 如果能匹配成功,这个m就会有值, 否则m为None  
    7 #不为空代表匹配上了
    8 
    9 print(m.group()) #m.group()返回匹配上的结果,此处为1,因为匹配上的是1这个字符  else:print("doesn't match.")

    上面的第2和第3行也可以合并成一行来写:

    1 m = p.match("^[0-9]",'14534Abc')

      效果是一样的,区别在于,第一种方式是提前对要匹配的格式进行了编译(对匹配公式进行解析),这样再去匹配的时候就不用在编译匹配的格式,第2种简写是每次匹配的时候 都 要进行一次匹配公式的编译,所以,如果你需要从一个5w行的文件中匹配出所有以数字开头的行,建议先把正则公式进行编译再匹配,这样速度会快点。

     

    匹配格式

    模式

    描述

    ^

    匹配字符串的开头

    $

    匹配字符串的末尾。

    .

    匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符。

    [...]

    用来表示一组字符,单独列出:[amk] 匹配 'a','m'或'k'

    [^...]

    不在[]中的字符:[^abc] 匹配除了a,b,c之外的字符。

    re*

    匹配0个或多个的表达式。

    re+

    匹配1个或多个的表达式。

    re?

    匹配0个或1个由前面的正则表达式定义的片段,非贪婪方式

    re{ n}

     

    re{ n,}

    精确匹配n个前面表达式。

    re{ n, m}

    匹配 n 到 m 次由前面的正则表达式定义的片段,贪婪方式

    a| b

    匹配a或b

    (re)

    G匹配括号内的表达式,也表示一个组

    (?imx)

    正则表达式包含三种可选标志:i, m, 或 x 。只影响括号中的区域。

    (?-imx)

    正则表达式关闭 i, m, 或 x 可选标志。只影响括号中的区域。

    (?: re)

    类似 (...), 但是不表示一个组

    (?imx: re)

    在括号中使用i, m, 或 x 可选标志

    (?-imx: re)

    在括号中不使用i, m, 或 x 可选标志

    (?#...)

    注释.

    (?= re)

    前向肯定界定符。如果所含正则表达式,以 ... 表示,在当前位置成功匹配时成功,否则失败。但一旦所含表达式已经尝试,匹配引擎根本没有提高;模式的剩余部分还要尝试界定符的右边。

    (?! re)

    前向否定界定符。与肯定界定符相反;当所含表达式不能在字符串当前位置匹配时成功

    (?> re)

    匹配的独立模式,省去回溯。

    w

    匹配字母数字

    W

    匹配非字母数字

    s

    匹配任意空白字符,等价于 [ f].

    S

    匹配任意非空字符

    d

    匹配任意数字,等价于 [0-9].

    D

    匹配任意非数字

    A

    匹配字符串开始

    

    匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符串。c

    z

    匹配字符串结束

    G

    匹配最后匹配完成的位置。

    

    匹配一个单词边界,也就是指单词和空格间的位置。例如, 'er' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。

    B

    匹配非单词边界。'erB' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。

    , , 等.

    匹配一个换行符。匹配一个制表符。等

    1...9

    匹配第n个分组的子表达式。

    10

    匹配第n个分组的子表达式,如果它经匹配。否则指的是八进制字符码的表达式。

    正则表达式常用5种操作 

    re.match(pattern,string)     #从头到尾

    re.search(patten,string)      #匹配整个字符串,直到找到一个匹配

     

    re.split()                            #将匹配到的格式当做分割点对字符串分割成列表

    1 import re
    2 
    3 #匹配0-9之间的数字,将匹配到的格式当做分割点将字符串分割成列表
    4 m = re.split("[0-9]","alex1rain2jack3helen rache18Lyon")
    5 print(m)
    6 #输出:['alex', 'rain', 'jack', 'helen rache', '', 'Lyon']

     

     

    re.findall()                       #找到所有要匹配的字符并返回列表格式

    1 #匹配0-9之间的数字,将匹配到的字符返回列表格式
    2 m = re.findall("[0-9]","alex1rain2jack3helen rache18Lyon")
    3 print(m)
    4 #输出:['1', '2', '3', '1', '8']

     

     

    re.sub(pattern,repl,string,count,flag)    #替换匹配到的字符

    1 #匹配0-9之间的数字并将其替换成|,count 两次
    2 m = re.sub("[0-9]","|", "alex1rain2jack3helen rachel8",count=2)
    3 print(m)
    4 #输出:alex|rain|jack3helen rachel8

     

     

    正则表达式实例

    字符匹配

    字符

    描述

    .

    匹配任意一个字符(除了 )

    d D

    数字/非数字

    s S

    空白/非空白字符

    w W

    单词字符[a-zA-Z0-9]/非单词字符

     B

    单词边界,一个w与W之间的范围,顺序可逆/非单词边界

     

     

     

     

     

     

     

     

     

    匹配任意一个字符

    1 #匹配字符串abc,.代表b
    2 m = re.match('a.c','abcd')
    3 #m.group()返回匹配到的结果
    4 print(m.group())
    5 #输出:abc

     

     数字与非数字

    1 #匹配任意一数字
    2 m = re.match('d','1a')
    3 print(m.group())
    4 #匹配任意非数字
    5 m = re.match('D','a1')
    6 print(m.group())
    7 #输出:'1'
    8 #      'a'

     

     

    空白与非空白字符

    1 #匹配任意一个空白字符
    2 m = re.match('s',' a')
    3 print(m.group())
    4 #输出:' '
    5 #匹配任意一个非空白字符
    6 m = re.match('S','a ')
    7 print(m.group())
    8 #输出'a'

     

    单词字符与非单词字符

     1  # 匹配任意一个单词字符
     2  #单词字符即表达[a-zA-Z0-9]
     3 m = re.match("w","a")
     4 print(m.group())
     5 m = re.match("w","1")
     6 print(m.group())
     7 #输出:'a'
     8 #      '1' 
     9 #  匹配任意一个非单词字符
    10 m = re.match("W"," ")
    11 print(m.group())
    12 #输出:' '

     

    次数匹配

    字符

    匹配

    *

    匹配前一个字符0次或者多次

    +

    匹配前一个字符1次或者多次

    ?

    匹配前一个字符0次或者1次

    {m}/{m,n}

    匹配前一个字符m次或者N次

    *?/+?/??

    匹配模式变为贪婪模式(尽可能少匹配字符)

     

     

     

     

     

     

     

     

     

    介绍

    字符匹配
    prev? 0个或1个prev
    prev* 0个或多个prev,尽可能多地匹配
    prev*? 0个或多个prev,尽可能少地匹配
    prev+ 1个或多个prev,尽可能多地匹配
    prev+? 1个或多个prev,尽可能少地匹配
    prev{m} m个连续的prev
    prev{m,n} m到n个连续的prev,尽可能多地匹配
    prev{m,n}? m到n个连续的prev,尽可能少地匹配
    [abc] a或b或c
    [^abc] 非(a或b或c)

     

     

     

     

     

     

     

     

    匹配前一个字符0次或者多次

    1 m = re.match('[A-Z][a-z]*','Aaa')
    2 print(m.group())
    3 m = re.match('[A-Z][a-z]*','Aa')
    4 print(m.group())
    5 m = re.match('[A-Z][a-z]*','A')
    6 print(m.group())
    7 #输出:Aaa
    8 #     Aa
    9 #     A

     

    匹配前一个字符一次或者多次

     1 #匹配前一个字符1次或者多次
     2 m = re.match('[A-Z][a-z]+','A')
     3 #如果一次都没有就会报错
     4 print(m.group())
     5 m = re.match('[A-Z][a-z]+','Aaaaaaaaaa')
     6 print(m.group())
     7 #输出:Traceback (most recent call last):
     8 #          File "D:/Users/Desktop/python/day4/正则次数匹配.py", line 18, in <module>
     9 #               print(m.group())
    10 #      AttributeError: 'NoneType' object has no attribute 'group'
    11 
    12 #'Aaaaaaaaaa'

     

    匹配前一个字符0次或1次

    1 #匹配前一个字符0次或者1次
    2 m = re.match('[A-Z][a-z]?','A')
    3 print(m.group())
    4 #只匹配出一个
    5 m = re.match('[A-Z][a-z]?','Aaaa')
    6 print(m.group())
    7 #输出:A
    8 #     Aa

     

    匹配前一个字符m次或N次

     1 #匹配前一个字符至少5次
     2 m = re.match('w{5}','asd234')
     3 print(m.group())
     4 #匹配前面的字符6-10次
     5 m = re.match('w{6,10}','asd234')
     6 print(m.group())
     7 #超过的字符就匹配不出来
     8 m = re.match('w{5,10}','asd234fas321')
     9 print(m.group())
    10 #输出:asd23
    11 #      asd234
    12 #      asd234fas3

     

    匹配模式变为贪婪模式(尽可能少的匹配)

     1 m = re.match(r'[0-9][a-z]*','1bc')
     2 print(m.group())
     3 #*?匹配0次或者多次
     4 m = re.match(r'[0-9][a-z]*?','1bc')
     5 print(m.group())
     6 #+?匹配一次或多次,但是只匹配了一次
     7 m = re.match(r'[0-9][a-z]+?','1bc')
     8 print(m.group())
     9 #??匹配0次或者一次
    10 m = re.match(r'[0-9][a-z]??','1bc')
    11 print(m.group())
    12 #输出:1bc
    13 #      1
    14 #      1b
    15 #      1

     

    上面例子,在第一个引号前的r的作用为对要匹配的内容进行转义。

    python中使用字符串前面加r点击这里

    边界匹配

    字符

    匹配

    ^

    匹配字符串开头

    $

    匹配字符串结尾

    A 

    指定的字符串必须出现在开头/结尾

     

     

     

     

     

     

    匹配字符串开头

    1 #必须以指定的字符串开头,结尾必须是@163.com
    2 m = re.match('^[w]{4,6}@163.com$','adffd@163.com')
    3 print(m.group())
    4 #输出:adffd@163.com

     

    匹配字符串结尾

    1 #必须以.me结尾
    2 m = re.match('[w]{1,20}.me$','Lyon.me')
    3 print(m.group())
    4 #输出:Lyon.me

     

    指定的字符串必须出现在开头/结尾

    1 m = re.match(r'Awww[w]*me','wwwLyonme')
    2 print(m.group())
    3 #输出:wwwLyonme

     

    正则表达式分组匹配

    |匹配左右任意一个表达式

    1 1 m = re.match('www|me','www')
    2 2 print(m.group())
    3 3 m = re.match('www|me','me')
    4 4 print(m.group())
    5 5 #输出:www
    6 6 #     me    

     

    (ab)括号中表达式作为一个分组

    1 #匹配163或者126的邮箱
    2 m = re.match(r'[w]{4,6}@(163|126).com','adfsdf@163.com')
    3 print(m.group())
    4 m = re.match(r'[w]{4,6}@(163|126).com','adfsdf@126.com')
    5 print(m.group())
    6 #输出:adfsdf@163.com
    7 #      adfsdf@126.com

     

    (?P)分组起一个别名

    1 m = re.search('(?P<ziumu>abc)(?P<shuzi>123)','abc123')
    2 print(m.groups())
    3 print(m.group('ziumu'))
    4 print(m.group('shuzi'))
    5 # 输出:('abc', '123')
    6 #       abc
    7 #       123

     

    re.match与re.search的区别

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

     

    实列:

    1 import re
    2 phone_str = "hey my name is Lyon,and my phone number 13651066376,please call me if you are pretty!"
    3 #[358]匹配中括号内的任意一个字母
    4 m = re.search("(1)([358]d{9})", phone_str)
    5 if m:
    6     print(m.group())
    匹配手机号

     六、模块初识

     json和pickle

    用于序列化的两个模块

    • json,用于字符串和pyhton数据类型间的进行转换
    • picle,用于python特有的类型和python的数据类型间进行转换

    Json模块提供了四个功能:dumps、dump、loads、load

    Pickle模块提供了四个功能:dumps、dump、loads、load

    其它常用模块学习,点击这里

    注:本文仅为学习笔记、摘要。

    详细来源:http://www.cnblogs.com/alex3714/articles/5143440.html

         https://blog.ansheng.me/article/python-full-stack-way-regular-expressions/

  • 相关阅读:
    floating IP 原理分析
    创建 floating IP
    Why Namespace?
    虚拟 ​router 原理分析- 每天5分钟玩转 OpenStack(101)
    链接脚本使用一例2---将二进制文件 如图片、MP3音乐、词典一类的东西作为目标文件中的一个段
    linux-2.6.26内核中ARM中断实现详解(转)
    有关Cache –(1) linux list之中的Prefetc
    Linux 内核中的 GCC 特性
    对entry-common.S和call.S的部分理解1
    kernel&uboot学习笔记
  • 原文地址:https://www.cnblogs.com/lyonyang/p/6507656.html
Copyright © 2020-2023  润新知