re模塊練習

首先準備了一個通信錄文件:「嫩模聯繫方式」python

姓名        地區    身高    體重    電話
況詠蜜     北京    171    48    13651054608
王心顏     上海    169    46    13813234424
馬纖羽     深圳    173    50    13744234523
喬亦菲     廣州    172    52    15823423525
羅夢竹     北京    175    49    18623423421
劉諾涵     北京    170    48    18623423765
嶽妮妮     深圳    177    54    18835324553
賀婉萱     深圳    174    52    18933434452
葉梓萱    上海    171    49    18042432324
杜姍姍   北京    167    49       13324523342
通信錄文件

1.驗證手機號是否合法正則表達式

解析:手機號有11位,以1開頭,第二位爲三、四、8 —— ^1[348]\\d{9},\\d第一個表示轉義,'\d'爲產生任意數字,{9}爲剛好出現9次。ide

# -*- coding:utf-8 -*-
__author__ = 'Qiushi Huang'

import re


class IsCellphone():
    def __init__(self):
        self.p = re.compile('^1[348]\\d{9}')  # 公式編譯好了,直接拿去匹配提高效率

    def iscellphone(self, number):
        res = self.p.match(number)
        if res:
            return True
        else:
            return False


p = IsCellphone()
f = open("嫩模聯繫方式", "r")
data = f.read()
contacts = re.findall("[0-9]{11}", data)
for i in contacts:
    if p.iscellphone(i):
        print("%s 是正常號碼" % i)
    else:
        print("請檢查手機號碼%s" % i)
"""
13651054608 是正常號碼
13813234424 是正常號碼
13744234523 是正常號碼
請檢查手機號碼15823423525
18623423421 是正常號碼
18623423765 是正常號碼
18835324553 是正常號碼
18933434452 是正常號碼
18042432324 是正常號碼
13324523342 是正常號碼
"""

 

2.驗證郵箱是否合法spa

解析:郵箱必須有@符號,@符號前能夠爲字母、數字、下劃線、中劃線,@符號後通常爲一到兩個「.」中間爲小寫字母:3d

    表達式:code

re = "^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$"

  ^\w+:表示表達式以a-z,A-Z,0-9或下劃線開頭,帶上「+」表示一次或屢次出現。orm

  ([\.-]?\w+)*:方括號內包含字符\.- 是但願容許用戶輸入點號或連字符,可是點號對於正則表達式有特殊的意義,因此須要在它前面加上反斜槓\。blog

          方括號後?表示前面內容能夠出現一次或不出現。?後的\w+表示點號或連字符後面必須有其餘字符。遞歸

          括號()後的*表示()內內容能夠出現0次或屢次。ip

  @\w+:表示@符合,及@符號後必須有其餘字符

  (\.\w{2,3})+:表示會出現一個點號,點號後面會出現字符(2到3個字符),後面的+表示點號和字符的組合會出現一次到屢次

  $:正則表達式的末尾是一個美圓符號$ ,表示匹配的字符串必須在這裏結束

# 郵箱檢查
class IsMail():
    def __init__(self):
        self.p = re.compile(r'^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$')

    def ismail(self, str):
        res = self.p.match(str)
        if res:
            return True
        else:
            return False


p = IsMail()
f = open("嫩模聯繫方式", "r")
for k,v in enumerate(f):
    if k == 0:
        pass
    else:
        data = v.split(" "*5)
        mail_addr = data[5]
        if p.ismail(mail_addr):
            print("正常得郵箱地址%s" % mail_addr)
        else:
            print("請檢查郵箱地址%s" % mail_addr)
"""
正常得郵箱地址133123@qq.com

正常得郵箱地址wdasd@13.ad.asdw

請檢查郵箱地址sadw@*sad2.asdw

正常得郵箱地址wddada@sina.com

正常得郵箱地址asddwa@adwd.adww

正常得郵箱地址adwwd2@12313.sadw

請檢查郵箱地址asdwd2133@dedewd3

正常得郵箱地址asdwd2@dadwdw.dww

請檢查郵箱地址adwdadw@dwdw..wda

請檢查郵箱地址asdwd2@de13.d23*
"""

 

3.開發一個簡單的python計算器,實現加減乘除及拓號優先級解析

  • 用戶輸入 1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )等相似公式後,必須本身解析裏面的(),+,-,*,/符號和公式(不能調用eval等相似功能偷懶實現),運算後得出結果,結果必須與真實的計算器所得出的結果一致
        hint:
    
        re.search(r'\([^()]+\)',s).group()#可拿到最裏層的括號中的值 
    
        '(-40/5)'

  計算器思路:

    一、沒用使用遞歸,先找出並計算全部括號裏的公式,再計算乘除和加減
    二、全部的數字都認爲是浮點型操做,以此來保留小數

  流程圖:

 

# -*- coding:utf-8 -*-
__author__ = 'Qiushi Huang'

import re
import functools


def minus_operator_handler(formula):
    """處理一些特殊的減號運算"""
    minus_operators = re.split("-", formula)    # 以匹配到的字符當作列表分隔符
    calc_list = re.findall("[0-9]", formula)    # 把全部匹配到的字符放到以列表中的元素返回
    if minus_operators[0] == '':   # 第一個值爲負號
        calc_list[0] = "-%s" % calc_list[0]
    res = functools.reduce(lambda x,y:float(x) - float(y), calc_list)
    print("\033[33;1m減號[%s]處理結果:\033[0m" % formula, res)
    return res


def remove_duplicates(formula):
    """刪除重複的加減符號"""
    formula = formula.replace("++", "+")
    formula = formula.replace("+-", "-")
    formula = formula.replace("-+", "-")
    formula = formula.replace("--", "+")
    formula = formula.replace("- -", "+")
    return formula


def compute_multiply_and_dividend(formula):
    """算乘除法,傳入的是字符串"""
    operators = re.findall("[*/]", formula)
    calc_list = re.split("[*/]", formula)
    res = None
    for index, i in enumerate(calc_list):
        if res:
            if operators[index-1] == "*":
                res *= float(i)
            elif operators[index-1] == "/":
                res /= float(i)
        else:
            res = float(i)

    print("\033[31;1m[%s]運算結果=\033[0m" % formula, res)
    return res


def handle_minus_in_list(operator_list, calc_list):
    """
    有的時候把算術符和值分開後,會出現這種狀況  ['-', '-', '-'] [' ', '14969037.996825399 ', ' ', '12.0/ 10.0 ']
    這須要把第2個列表中的空格都變成負號並與其後面的值拼起來,噁心死了
    """
    for index, i in enumerate(calc_list):
        if i == '':   # 它實際上是表明負號,改成負號
            calc_list[index+1] = i + calc_list[index+1].strip()


def handle_special_occactions(plus_and_minus_operators, multiply_and_dividend):
    '''有時會出現這種狀況 , ['-', '-'] ['1 ', ' 2 * ', '14969036.7968254'],2*...後面這段實際是 2*-14969036.7968254,須要特別處理下,太噁心了'''
    for index,i in enumerate(multiply_and_dividend):
        i = i.strip()
        if i.endswith("*") or i.endswith("/"):
            multiply_and_dividend[index] = multiply_and_dividend[index] + \
                                           plus_and_minus_operators[index] + multiply_and_dividend[index+1]
            del multiply_and_dividend[index+1]
            del plus_and_minus_operators[index]
    return plus_and_minus_operators, multiply_and_dividend


def compute(formula):
    """這裏的計算是去除括號的"""
    formula = formula.strip("()")   # 去除外面的括號
    formula = remove_duplicates(formula)   # 去除重複的+-號

    plus_and_minus_operators = re.findall("[+-]", formula)
    multiply_and_dividend = re.split("[+-]", formula)  # 取出乘除公式
    if len(multiply_and_dividend[0].strip()) == 0:   # 表明這確定是個減號
        multiply_and_dividend[1] = plus_and_minus_operators[0] + multiply_and_dividend[1]
        del multiply_and_dividend[0]
        del plus_and_minus_operators[0]

    plus_and_minus_operators, multiply_and_dividend=handle_special_occactions(plus_and_minus_operators, multiply_and_dividend)
    for index, i in enumerate(multiply_and_dividend):
        if re.search("[*/]", i):
            sub_res = compute_multiply_and_dividend(i)
            multiply_and_dividend[index] = sub_res
    """開始運算+,-"""
    print(multiply_and_dividend, plus_and_minus_operators)
    total_res = None
    for index, item in enumerate(multiply_and_dividend):
        if total_res:   # 表明不是第一次循環
            if plus_and_minus_operators[index-1] == '+':
                total_res += float(item)
            elif plus_and_minus_operators[index-1] == '-':
                total_res -= float(item)
        else:
            total_res = float(item)
    print("\033[32;1m[%s]運算結果:\033[0m" %formula,total_res)
    return total_res


def calc(formula):
    """計算程序主入口,主要邏輯是先計算括號裏的值,再計算乘除,再計算加減"""
    parenthesise_flag = True
    calc_res = None   # 初始化運算結果爲None
    while parenthesise_flag:
        m = re.search("\([^()]*\)", formula)   # 找到最裏層括號
        # <_sre.SRE_Match object; span=(18, 25), match='(-40/5)'>
        if m:
            print("先算括號裏的值:", m.group())   # '(-40/5)'
            sub_res = compute(m.group())
            formula = formula.replace(m.group(), str(sub_res))
        else:
            print('\033[41;1m----沒括號了...---\033[0m')

            print('\n\n\033[42;1m最終結果:\033[0m',compute(formula))
            parenthesise_flag = False   # 表明公式裏的括號已經都被剝除了


if __name__ == '__main__':
    res = calc("1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )")

"""執行結果以下:
先算括號裏的值: (-40/5)
[-40/5]運算結果= -8.0
[-8.0] []
[-40/5]運算結果: -8.0
先算括號裏的值: (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )
[2*5/3 ]運算結果= 3.3333333333333335
[ 7 /3*99/4*2998 ]運算結果= 173134.50000000003
[10 * 568/14 ]運算結果= 405.7142857142857
['9', 3.3333333333333335, 173134.50000000003, 405.7142857142857] ['-', '+', '+']
[9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 ]運算結果: 173545.88095238098
先算括號裏的值: (60-30 +-8.0 * 173545.88095238098)
[8.0 * 173545.88095238098]運算結果= 1388367.0476190478
['60', '30 ', 1388367.0476190478] ['-', '-']
[60-30 -8.0 * 173545.88095238098]運算結果: -1388337.0476190478
先算括號裏的值: (-4*3)
[-4*3]運算結果= -12.0
[-12.0] []
[-4*3]運算結果: -12.0
先算括號裏的值: (16-3*2)
[3*2]運算結果= 6.0
['16', 6.0] ['-']
[16-3*2]運算結果: 10.0
先算括號裏的值: ( -1388337.0476190478 - -12.0/ 10.0 )
[12.0/ 10.0 ]運算結果= 1.2
['-1388337.0476190478 ', 1.2] ['+']
[ -1388337.0476190478 +12.0/ 10.0 ]運算結果: -1388335.8476190479
----沒括號了...---
[ 2 * -1388335.8476190479]運算結果= -2776671.6952380957
['1 ', -2776671.6952380957] ['-']
[1 - 2 * -1388335.8476190479]運算結果: 2776672.6952380957


最終結果: 2776672.6952380957
"""
相關文章
相關標籤/搜索