[Python][华为云Python编程创造营][课堂实验代码][应用篇]

举报
John2021 发表于 2022/03/10 21:32:08 2022/03/10
【摘要】 咬文嚼字 实验介绍本实验介绍了Python中通过标准库re模块实现正则表达式的使用 实验代码 re模块的使用 步骤1,匹配方法的使用'''re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none'''# 导入re模块import reprint(re.match('www', 'www.huawei.com').span()) # ...

咬文嚼字

实验介绍

  • 本实验介绍了Python中通过标准库re模块实现正则表达式的使用

实验代码

re模块的使用

步骤1,匹配方法的使用

'''
re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none
'''
# 导入re模块
import re

print(re.match('www', 'www.huawei.com').span())  # (0, 3)
print(re.match('com', 'www.huawei.com'))  # None
'''
re.search 扫描整个字符串并返回第一个成功的匹配
'''
print(re.search('www', 'www.huawei.com').span())  # (0, 3)
print(re.search('com', 'www.huawei.com').span())  # (11, 14)

步骤2,compile方法的使用

'''
re.complie函数用于编译正则表达式,生成一个正则表达式(Pattern)对象,供match()和search()这两个函数使用
'''
import re

pattern = re.compile(r'\d+')  #用于匹配至少一个数字
n = pattern.match('one12twothree34four')  #查找头部,没有匹配
print(n)  #None
# 从'e'的位置开始匹配,没有匹配
m = pattern.search('one12twothree34four')
print(m)  #<re.Match object; span=(3, 5), match='12'>
print(m.group())  #12

步骤3,re模块其他方法的使用

'''
re.sub用于替换字符串中的匹配项
'''
import re

phone = '2021-0101-000'  #这是一个电话号码
# 删除字符串中的Python注释
num = re.sub(r'#.*$', '', phone)
print('电话号码是:', num)  #电话号码是: 2021-0101-000
# 删除非数字(-)的字符串
num = re.sub(r'\D', '', phone)
print('电话号码是:', num)  #电话号码是: 20210101000
'''
re.findall方法查找所有符合条件的文本
'''
phone = '2021-0101-000 #这是一个电话号码0'
# 查找所有的0
num = re.findall(r'0', phone)
print(num)  #['0', '0', '0', '0', '0', '0', '0']
'''
re.split方法按照能够匹配的子串将字符串分割后返回列表
'''
# re.split(pattern,string[,maxsplit=0,flags=0])
phone = '2021-0101-000 #这是一个电话号码'
print(re.split(r'-', phone))  #['2021', '0101', '000 #这是一个电话号码']

步骤4,正则表达式修饰符

# 正则表达式可以包含一些可选标志修饰符来控制匹配的模式。修饰符被指定为一个可选的标志
# re.I 对大小写不敏感
import re

str_ = 'Life is short, you need Python'
r1 = re.match('life is short', str_)
r2 = re.match('Life is short', str_, flags=re.I).group()
print(r1)  #None
print(r2)  #Life is short

正则表达式基础

步骤1,匹配数字

'''
使用正则表达式来匹配数字
'''
import re

# 匹配文本中的所有数字
str_ = '1海绵宝宝2派大星'
num1 = re.findall(r'\d+', str_)  #使用\d匹配数字,+表示匹配多次
print(num1)
num2 = re.findall(r'[0-9]{1,3}', str_)  #正则表达式不唯一,可以使用[]指定匹配元素的范围,{}指定次数
print(num2)

步骤2,匹配字符

'''
使用\w可以匹配数字字母下划线
'''
import re

str_ = '1海绵宝宝HAI2派大星,_动画片_,PAI'
s1 = re.findall(r'\w+', str_)
print(s1)  #['1海绵宝宝HAI2派大星', '_动画片_', 'PAI']
'''
使用\S匹配任意非空字符
'''
s2 = re.findall(r'\S+', str_)
print(s2)  #['1海绵宝宝HAI2派大星,_动画片_,PAI']
'''
只匹配英文字母
'''
# 在文本中匹配英文
s3 = re.search(r'[A-Za-z]+', str_).group()
print(s3)  #HAI
'''
匹配任意的非数字字符\D
'''
s4 = re.findall(r'\D+', str_)
print(s4)  #['海绵宝宝HAI', '派大星,_动画片_,PAI']
'''
只匹配中文
'''
# 匹配文本中所有的汉字
s5 = re.findall(r'[\u4e00-\u9fa5]{1,}', str_)  #两个\u开头的unicode值正好是Unicode表中的汉字头和尾
print(s5)  #['海绵宝宝', '派大星', '动画片']

步骤3,匹配符号

# 匹配文本中的所有符号
s6 = re.findall(r'\W+', str_)
print(s6)  #[',', ',']

正则表达式使用

步骤1,匹配文本信息中的邮箱信息

import re

# 匹配文本中的邮箱
str_ = '我的邮箱是python123@py.com'
s = re.findall(r'[A-Za-z0-9]+@[A-Za-z0-9]+\.com', str_)
print(s)  #['python123@py.com']

步骤2,匹配网址URL

import re

str_ = '我的个人主页:https://www.python.org'
s = re.findall(r'[A-Za-z]+://[^\s]*', str_)
print(s)  #['https://www.python.org']

步骤3,匹配身份证号码

import re

str_ = '我的身份证号码是12345678901234567X'
s = re.findall(r'(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})([0-9]|X)', str_)
print(s)  #[('123456', '7890', '12', '34', '567', 'X')]
print(''.join(s[0]))  #12345678901234567X

步骤4,匹配手机号码

import re

str_ = '我的手机号码是12345678901'
s = re.findall(r'\d{3}\d{8}|\d{4}\{7,8}', str_)
print(s)  #['12345678901']

步骤5,贪婪模式下的匹配

import re

html = "aa<div>test1</div>bb<div>test2</div>cc "
res = re.search('<div>.*<div>', html)
print(res.group())  #<div>test1</div>bb<div>

步骤6,非贪婪模式下的匹配

import re

html = 'aa<div>test1</div>bb<div>test2</div>cc'
res = re.search('<div>.*?</div>', html)
print(res.group())  #<div>test1</div>

看,那里有个BUG

实验介绍

  • 本实验介绍了Python中的异常及其处理方式和程序调试方法,包括了Python中已经定义好的异常、抛出自定义异常、程序断点调试

实验代码

Python中的异常

步骤1,代码错误

'''
代码不遵循语法规则所产生的错误
'''
# 缩进
# def func():
# pass
# return 0
# 语法
# def func()
#     pass
#     return 0

步骤2,异常

# 除数为0
def func():
    return 1 / 0


func()
# 下标越界
list1 = [1, 2]


def func():
    return list1[3]


func()
# 文件不存在
with open('file.file') as f:
    f.read()

步骤3,异常处理

# 使用try进行捕获
def func(num):
    return 1 / num


try:
    num = 0
    func(num)
except ZeroDivisionError:
    print('num不能为0')


# 直接捕获Exception
def func(num):
    return 1 / num


def func2():
    l = [1]
    return l[1]


try:
    num = 1
    func(num)
    func2()
except Exception as e:
    print(e)
# 捕获错误代码
try:
    def func():
        pass
        return 0
except Exception as e:
    print(e)

步骤4,finally

def func2():
    l = [1]
    return l[1]


try:
    func2()
except Exception as e:
    print(e)
finally:
    print('------')

步骤5,自定义异常

# 通过搜索Exception的方式实现自定义异常
class MyException(Exception):
    def __init__(self, msg=None):
        self.msg = msg

    def __str__(self):
        return str(self.msg)


age = 17


def func(age):
    if 100 > age > 18:
        return 1
    else:
        raise MyException('未成年人不能进网吧')


func(17)

程序调试

步骤1,main

# myPY.py
def a():
    print('hello myPY.py')


if __name__ == '__main__':
    print(__name__)
    a()
'''
运行a.py输出
__main__
hello myPY.py
'''
# mytest.py
import myPY

print(myPY.__name__)  # a

步骤2,print

# 使用print打印可能存在问题的信息
def foo(s):
    n = int(s)
    print('n=%d' % n)
    return 10 / n


def main():
    foo('0')


main()
'''
输出结果:
ZeroDivisionError: division by zero
n=0
'''

步骤3,assert

def foo(num):
    assert type(num) == int, 'num必须为整形'
    assert num != 0, 'n is zero'
    return 10 / num


foo('0')
'''
输出结果:
    assert type(num) == int,'num必须为整形'
AssertionError: num必须为整形
'''
# 运行带有assert语句时,可以通过 -O 参数来屏蔽assert

步骤4,断点调试

# 通过断点来查看程序的运行状态
def fibonaccis():
    result = [0, 1]
    for i in range(2, 10):
        a = result[i - 1] + result[i - 2]
        result.append(a)
    return result


fibonaccis()

步骤5,单元测试

# 通过Python提供的unittest实现单元测试
from myPY import CheckUserInfo
import unittest


class CheckUserInfoTestCase(unittest.TestCase):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.check_user_info = CheckUserInfo()

    @classmethod
    def setUpClass(cls):
        print('setUpClass\n\n')

    @classmethod
    def tearDownClass(cls):
        print('tearDownClass')

    def setUp(self):
        print('setUp')

    def tearDown(self):
        print('tearDown\n')

    def test_check_pwd_len(self):
        print('test_check_pwd_len')
        self.assertEqual(True, self.check_user_info.check_pwd_len('12345678'))
        self.assertEqual(False, self.check_user_info.check_pwd_len(''))
        self.assertEqual(False, self.check_user_info.check_pwd_len('1'))
        self.assertEqual(True, self.check_user_info.check_pwd_len('123456789'))

    def test_check_pwd_contain_letter(self):
        print('test_check_pwd_contain_letter')
        self.assertEqual(True, self.check_user_info.check_pwd_contain_letter('1qazXSW@'))
        self.assertEqual(False, self.check_user_info.check_pwd_contain_letter(''))

    def aaa(self):
        print('test_check_pwd_contain_num')
        self.assertEqual(True, self.check_user_info.check_pwd_contain_num('1qazXSW@'))
        if __name__ == '__main__':
            unittest.main()
# 执行测试
# python mytest.py

三个神器

实验介绍

  • 本实验介绍了Python中迭代器、生成器和装饰器,包括了在Python中如何定义及使用这三个工具

实验代码

迭代器和生成器

步骤1,迭代

# 使用for循环对数据做迭代
List = [1, 2, 3]
str_ = 'py3'
Tuple = (9, 8, 7)
Dict = {'a': 1, 'b': 2, 'c': 3}
Set = {'a', 'b', 'c'}
for i in zip(List, str_, Tuple, Dict, Set):
    print(i)
'''
输出结果:
(1, 'p', 9, 'a', 'a')
(2, 'y', 8, 'b', 'c')
(3, '3', 7, 'c', 'b')
'''

步骤2,可迭代对象

# 使用Iterable来判断数据是否是可迭代对象
List = [1, 2, 3]
str_ = 'py3'
Tuple = (9, 8, 7)
Dict = {'a': 1, 'b': 2, 'c': 3}
Set = {'a', 'b', 'c'}

from collections.abc import Iterable

print('list: ', isinstance(List, Iterable))
print('str: ', isinstance(str_, Iterable))
print('tuple: ', isinstance(Tuple, Iterable))
print('dict: ', isinstance(Dict, Iterable))
print('set: ', isinstance(Set, Iterable))
print('num: ', isinstance(1, Iterable))
'''
输出结果:
list:  True
str:  True
tuple:  True
dict:  True
set:  True
num:  False
'''

步骤3,实现一个可迭代对象

from collections.abc import Iterable


class Iter_obj(object):
    def __init__(self, value):
        self.value = value

    def __iter__(self):
        self.index = 3
        return iter(self.value[:self.index])


L = Iter_obj([1, 2, 3, 4, 5, 6])
print(isinstance(L, Iterable))
for i in L:
    print(i)
'''
输出结果:
True
1
2
3
'''

步骤4,迭代器对象

# 判断对象是否是迭代器
List = [1, 2, 3]
str_ = 'py3'
Tuple = (9, 8, 7)
Dict = {'a': 1, 'b': 2, 'c': 3}
Set = {'a', 'b', 'c'}

from collections.abc import Iterator

print('list: ', isinstance(List, Iterator))
print('str: ', isinstance(str_, Iterator))
print('tuple: ', isinstance(Tuple, Iterator))
print('dict: ', isinstance(Dict, Iterator))
print('set: ', isinstance(Set, Iterator))
print('num: ', isinstance(1, Iterator))
'''
输出结果:
list:  False
str:  False
tuple:  False
dict:  False
set:  False
num:  False
'''
# 可迭代对象不一定是迭代器对象
# 创建迭代器对象
l = iter([1, 2, 3])
d = iter({'a': 1, 'b': 2})
print(isinstance(l, Iterator))
print(isinstance(d, Iterator))
'''
输出结果:
True
True
'''

步骤5,for循环中的迭代器对象

# 迭代器在for循环中的使用
l = [1, 2, 3]
for i in l:
    print(i)
l = iter(l)
for i in l:
    print(i)
'''
输出结果:
1
2
3
1
2
3
'''

步骤6,next

d = iter({'a': 1, 'b': 2})
print(next(d))  #a
print(next(d))  #b

步骤7,实现一个迭代器对象

from collections.abc import Iterable


class IterObj:
    def __init__(self, value):
        self.value = value
        self.i = 0

    def __iter__(self):
        return iter(self.value)

    def __next__(self):
        while self.i < len(self.value):
            v = self.value[self.i]
            self.i += 1
            return v
        # 此处可以增加StopIteration


ite = IterObj([1, 2, 3, 4, 5])
print(isinstance(ite, Iterable))
next(ite)

步骤8,生成器

# 定义生成器
G = (x * 2 for x in range(5))
print(type(G))  #<class 'generator'>
# 生成器取值
print(next(G))  #0
print(next(G))  #2
print(next(G))  #4

步骤9,yield

# 通过yield创建生成器函数
def fib(n):
    current = 0
    num1, num2 = 0, 1
    while current < n:
        num = num1
        num1, num2 = num2, num1 + num2
        current += 1
        yield num
    return 'done'


g = fib(5)
while True:
    try:
        x = next(g)
        print('value: %d' % x)
    except StopIteration as e:
        print('生成器返回值: %s' % e.value)
        break
'''
输出结果:
value: 0
value: 1
value: 1
value: 2
value: 3
生成器返回值: done
'''

步骤10,send

# 除了使用next方法之外,还可以使用send方法唤醒生成器,
# 相比于next方法,send在唤醒生成器时还可以向断点处传入一个数据
def gen():
    i = 0
    while i < 5:
        temp = yield i
        print(temp)
        i += 1


f = gen()
print(next(f))
f.send('hahaha')
print(next(f))
'''
输出结果:
0
hahaha
None
2
'''

装饰器

步骤1,闭包

# 定义闭包函数
def func():
    temp = [lambda x: x * i for i in range(4)]
    return temp


for m in func():
    print(m(3))

步骤2,装饰器

# 定义装饰器函数,功能用于计算程序运行时间,
# 由于不清楚所装饰的函数的参数,通过不定长参数实现一个通用装饰器
import time


def func(f):
    def inner(*args, **kwargs):
        start_time = time.time()
        f(*args, **kwargs)
        end_time = time.time()
        print('耗时:%s秒' % (end_time - start_time))

    return inner


# 定义被装饰函数
@func
def test():
    time.sleep(2)


test()  #耗时:2.0001728534698486秒

步骤3,装饰器的执行流程

  • 将上述定义好的装饰器放在支持断点调试的IDE中,打上断点查看执行过程

步骤4,wraps

# 通过上述流程可以发现函数内部发生了变化,查看其元信息
@func
def sleep():
    '''我是一个函数,名字为sleep'''
    time.sleep(2)


help(sleep)
'''
Help on function inner in module __main__:

inner(*args, **kwargs)
'''
# 使用wraps,保留元信息,修改装饰器函数
import time
from functools import wraps


def func(f):
    @wraps(f)
    def inner(*args, **kwargs):
        start_time = time.time()
        f(*args, **kwargs)
        end_time = time.time()
        print('耗时:%s秒' % (end_time - start_time))

    return inner


# 重新装饰
@func
def sleep():
    '''我是一个函数,名字为sleep'''
    time.sleep(2)


help(sleep)
'''
输出结果:
Help on function sleep in module __main__:

sleep()
    我是一个函数,名字为sleep
'''

步骤5,带有外部参数的装饰器

# 可以发现wraps本身就是一个需要接受参数的装饰器,现在定义一个类似的装饰器
def Decorator(name=None, level='普通会员'):
    def outer(func):
        def inner(name):
            print('欢迎登陆, %s' % level)
            func(name)

        return inner

    return outer


@Decorator(level='SVIP')
def func(name):
    print(name)


func('张三')
'''
输出结果:
欢迎登陆, SVIP
张三
'''

步骤6,在类中使用装饰器

def singleton(cls, *args, **kwargs):
    instance = {}

    def _singleton():
        if cls not in instance:
            instance[cls] = cls(*args, **kwargs)
        return instance[cls]

    return _singleton


@singleton
class Singleton(object):
    def __init__(self):
        self.num_sum = 0

    def add(self):
        self.num_sum = 100

步骤7,类装饰器

class Tiga():
    def __init__(self, f):
        self.f = f

    def __call__(self, *args, **kwargs):
        print('叮,变身')
        self.f(*args, **kwargs)
        print('光之巨人')

    def Red(self, f):
        def wrapper(*args, **kwargs):
            print('切换战士状态:力量+100')
            f(*args, **kwargs)

        return wrapper

    @classmethod
    def Blue(cls, f):
        def wrapper(*args, **kwargs):
            print('切换刺客状态:敏捷+100')
            f(*args, **kwargs)

        return wrapper


@Tiga
def func():
    print('化身成为光')


func()


@Tiga.Blue
def fight1():
    print('速度很快,但是没有攻防')


fight1()


@func.Red
def fight2():
    print('使出一拳重击,但是没打中')


fight2()
'''
输出结果:
叮,变身
化身成为光
光之巨人
切换刺客状态:敏捷+100
速度很快,但是没有攻防
切换战士状态:力量+100
使出一拳重击,但是没打中
'''

步骤8,多个装饰器

def Tiga(func):
    print('给我力量吧,Tiga')

    def tiga():
        func()
        print('获得Tiga的力量')

    return tiga


def Dyna(func):
    print('给我力量吧,Dyna')

    def dyna():
        func()
        print('获得Dyna的力量')

    return dyna


def Gaia(func):
    print('给我力量吧,Gaia')

    def gaia():
        func()
        print('获得Gaia的力量')

    return gaia


@Tiga
@Dyna
@Gaia
def z():
    print('攻击攻击攻击')


z()
'''
输出结果:
给我力量吧,Gaia
给我力量吧,Dyna
给我力量吧,Tiga
攻击攻击攻击
获得Gaia的力量
获得Dyna的力量
获得Tiga的力量
'''

步骤9,解除装饰器

# 在使用装饰器后,如果需要解除只使用之前函数的功能
def light(func):
    print('获得神光棒x1')

    @wraps(func)
    def tiga():
        func()
        print('我是光之巨人')

    return tiga


@light
def person():
    print('我是某胜利队队员大骨')


DaGu = person.__wrapped__
DaGu()
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。