类装饰器以及正则表达式

1.类装饰器

1.类装饰器语法 @函数名
2.类装饰器 @类名


@类名 #comment=类名(comment)
def comment():
pass
# 调用
comment()
1.comment=类名(comment),等号右边是创建对象的语法,实参传递给__init__方法中,init方法中需要以形参接受 原函数,故init方法 等价于 外层函数
2.原函数被装饰之后,comment 就是 该类对象,对象(),会调用类的__call__这个魔法方法,即__call__方法,等价于内层函数
# 定义类装饰器
# 1.定义类,书写init方法,等价外层函数
class LoginCheck(object):
    def __init__(self, fn):
        self.__fn = fn

    # 2.书写__call__方法,等价于内层函数
    def __call__(self, *args, **kwargs):
        # 3.书写添加的新的功能
        print('请先登录...')
        # 4.调用原函数
        res = self.__fn(*args, **kwargs)
        return res


@LoginCheck  # comment=LoginCheck(comment)
def comment(info):
    print(info)


if __name__ == '__main__':
    comment('hello world')

书写带参数类装饰器

class MakeTag():
  pass
@MakeTag
def comment(info):
    pass

-----------------
分析:
1.MakeTag('div') 创建对象,实参, 'div' 给init方法中的形参,故确定init方法中需要一个形参接收这个参数
2.
@对象
def comment(info):
   pass
这个代码等价于 comment=对象(comment),对象(comment)调用__call__方法,__call__方法需要有一个形参,
接受原函数,等价于外层函数
3.__call__f返回内层函数的地址
# ----带参数的类装饰器----
class MakeTag(object):
    def __init__(self, tag):
        self.tag = tag

    def __call__(self, fn):
        def inner(*args, **kwargs):
            result = fn(*args, **kwargs)
            return f'<{self.tag}>+ {result}+{self.tag}'

        return inner

@MakeTag('div')
def comment(info):
    return info


if __name__ == '__main__':
    print(comment('hello world'))

2.propetry属性的介绍

1.property属性就是负债把一个方法当做属性进行使用,这样做可以简化代码使用。

2.定义property属性有两种方式

  • 装饰器方式

  • 类属性方式

# ----property属性------
class Dog(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age

    # 定义共有方法,获取对象name属性
    def get_name(self):
        return self.name

    # 定义共有方法,设置对象name属性
    def set_name(self, name):
        self.name = name

    # 通过类属性的方式,给对象添加property属性
    # property(获取属性值的方法,设置属性值的方法)
    name1 = property(get_name, set_name)

    # def get_age(self):
    #     return self.age
    # 
    # def set_age(self, age):
    #     self.age = age
    # 
    # name1 = property(get_name, set_name)

    @property
    def age(self):
        return self.age

    @age.setter
    def age(self, nwe_age):
        self.age = nwe_age


if __name__ == '__main__':
    # 创建对象
    # dog = Dog('小白', 13)
    # # 调用对象
    # print(dog.get_name())
    # dog.set_name('小白白')
    # # 调用对象
    # print(dog.get_name())
    dog = Dog('小白', 13)
    print(dog.name)
    dog.name = '小白白'
    print(dog.name)
    print(dog.age)
    dog.age = 1
    print(dog.age)
写代码的小规则:
   在类中,如果是获取属性的方法,一般不用print直接打印,一般会进行return返回这个属性值
如果是设置属性值,一半不需要设置返回值

3.with

#  -----------with语句----------
# 使用with语句,不需要书写关闭代码,会自动进行关闭
with open('a.txt','w') as f:
    f.write('hello world\n')
    f.write('hello python!!')
# with语句,代码除了with缩进之后,会自动的进行关闭
with 上下文管理器对象 as 变量名:
    pass
#  -----------with语句----------
# 使用with语句,不需要书写关闭代码,会自动进行关闭
# with open('a.txt', 'w') as f:
#     f.write('hello world\n')
#     f.write('hello python!!')


# with语句,代码除了with缩进之后,会自动的进行关闭


# 实现了__enter__和__exit__这两个魔法方法的类,就是上下文管理器对象类
class File(object):  # 实现文件操作
    def __init__(self, filename, mode):
        self.fp = open(filename, mode, encoding='utf-8')
        self.filename = filename
        self.mode = mode

    # 定义上文方法,__enter__,使用with语句,执行下方代码之前,会自动进入上文方法
    def __enter__(self):
        print('1.进入上面方法')
        self.fp = open(self.filename, self.mode, encoding='utf-8')
        return self.fp

    # 定义下文方法,with语句执行完成之后,会自动调用
    # with 语句中,即使发生异常,也会进入__exit__中
    def __exit__(self, exc_type, exc_val, exc_tb):
        # exc_type 发生异常时,异常的类型
        # exc_val  发生异常时,异常的信息
        # exc_tb   异常对象
        # 方法返回值,1.如果返回False(代码没有书写返回值,默认返回 None,False),代表发生异常
        # 以后,异常会继续向外传递。2.如果返回True,代表异常不在向外传递
        if exc_type:
            print('发生异常了.....')
        else:
            print('没有发生异常')
        print('2.进入了下文方法')
        self.fp.close()
        


if __name__ == '__main__':
    with File('a.txt', 'r') as f:
        print('3.我是 with语句中代码')

4.生成器

生成器推导式

列表推导式,快速的生成一组数据,一次性将数据全部生成的
# 变量=[生成数据的规则 for i in ..] 每循环一次,回向列表中根据生成数据的规则添加数据
# ------生成器推导式------------
my_list = ['hello' for i in range(5)]
print(my_list)
# 生成器推导式,语法和列表推导式非常像,只是将[]变为小括号,差异:生成器存储的生成数据的规则
# 使用一个数据就生成一个数据,好处:节省内存
my_gen = (i for i in range(5))
print(my_gen)
# 从生成器中获取数据,next(生成器)
num = next(my_gen)  # 0
print(num)
print(next(my_gen))  # 1
print(next(my_gen))  # 2
print(next(my_gen))  # 3
print(next(my_gen))  # 4
# 当生成数据的规则不满足之后StopIteration 异常
# print(next(my_gen))  # 此时,生成数据的规则已经不满足了,如果再次使用 next() 获取数据,会发生异常
# 获取 生成器中的数据,比较好用的方法式 for 循环,for 循环,python已经封装好了 StopIteration的异常
# 处理
for i in my_gen:
    print(i)
# 无法运行,已经把生成器数据获取完了

5.yield生成器

只有在def函数里面看到有yield关键字那么就是生成器

# --------yield生成器-----------
def func():
    for i in range(5):
        print(f'第{i + 1}次循环开始')
        # yield 关键字作用 1.类似return ,将会将后边跟的内容进行返回
        # 函数代码遇到yield,函数会暂停执行
        yield 100 + i
        print(f'第{i + 1}次循环结束')


if __name__ == '__main__':
    # 1.创建一个生成器对象
    my_gen = func()  # 此处,不是函数调用,是创建生成器,不会执行函数中 代码
    print(my_gen, type(my_gen))
    # res = next(my_gen)
    # print(res)
    # res = next(my_gen)
    # print(res)
    for i in my_gen:
        print(i)

6.斐波那锲数列

# ------------斐波那锲数列------------
def fibonacci(n):
    # 参数n代表要生成多少个数列
    a = 0
    b = 1
    for j in range(n):
        # 循环一次,就生成一个数据
        yield a
        a, b = b, a + b


if __name__ == '__main__':
    my_list = fibonacci(6)
    for i in my_list:
        print(i, end=' ')

7.yield实现协程(多任务)

# ----------yield实现协程------------
def sing():
    for i in range(5):
        print('正在唱歌....')
        yield


def dance():
    for j in range(5):
        print('正在跳舞.....')
        yield


if __name__ == '__main__':
    my_sing = sing()
    my_dance = dance()
    is_sing=None
    is_dance=None
    while True:
        try:
            next(my_sing)
        except StopIteration:
            pass
        try:
            next(my_dance)
        except StopIteration:
            break
        if is_sing and is_dance:  # 只有两个都为True,结果为True,才会结束循环
            break

8.深拷贝和浅拷贝(理解)

浅拷贝

  1. copy函数是浅拷贝,只对可变类型的第一层对象进行拷贝,对拷贝的对象开辟新的内存空间进行储存,不会拷贝对象内部的子对象

# 浅拷贝,copy.copy() 只会对可变类型的第一层对象进行拷贝,对拷贝的对象开辟内存空间,不会对内部的
# 子对象开辟空间
# 可变类型 list dict set
# 不可变类型 int float str tuple 对于不可变类型,浅拷贝不会开辟空间,拷贝的引用
# int
num = 10
num1 = copy.copy(10)
print(f'num:{id(num)}')
print(f'num1:{id(num)}')
# str
my_str = 'hello world'
my_str1 = copy.copy(my_str)
print(f'my_str:{id(num)}')
print(f'my_str1:{id(num)}')
# tuple
my_tuple = (1, 2, 3, [4, 5])
my_tuple1 = copy.copy(my_tuple)
print(f'my_tuple:{id(num)}')
print(f'my_tuple1:{id(num)}')
# 可变类型:list  dict set
my_list = [1, 2, [3, 4]]
my_list1 = copy.copy(my_list)
print(f'my_list:{id(my_list)},my_list[2]:{id(my_list[2])}')
print(f'my_list1:{id(my_list1)},my_list[2]:{id(my_list[2])}')

深拷贝

# ---------深拷贝---------
# copy.deepcopy(),深拷贝进行拷贝的时候,只要发现可变类型,就会对可变类型本身,已经父级对象进行拷贝
# int
num = 10
num1 = copy.deepcopy(10)
print(f'num:{id(num)}')
print(f'num1:{id(num)}')
# str
my_str = 'hello world'
my_str1 = copy.deepcopy(my_str)
print(f'my_str:{id(num)}')
print(f'my_str1:{id(num)}')
# tuple 如果元组中包含可变类型,回对元组本身以及子对象都开辟内存空间
my_tuple = (1, 2, 3, [4, 5])
my_tuple1 = copy.deepcopy(my_tuple)
print(f'my_tuple:{id(my_tuple)},my_tuple:{id(my_tuple[2])}')
print(f'my_tuple1:{id(my_tuple1)},my_tuple:{id(my_tuple1[2])}')
# 可变类型:list  dict set
my_list = [1, 2, [3, 4]]
my_list1 = copy.deepcopy(my_list)
print(f'my_list:{id(my_list)},my_list[2]:{id(my_list[2])}')
print(f'my_list1:{id(my_list1)},my_list[2]:{id(my_list[2])}')

9.正则介绍

正则表达式:记录文本规则的字符串。

re 模块使用

# re 模块使用
# 在python代码中,想要使用 正则表达式,需要导入 re模块
import re

# re.match(正则表达式,匹配文字)
# 返回值,匹配成功,返回对象 匹配失效,返回None
# result = re.match('0\d{2}-\d{8}', '010-12345678')
# re.search(正则表达式,匹配文字)  从任意位置进行匹配
result = re.search('0\d{2}-\d{8}', '1 010-12345678')
print(result)
if result:
    print(result.group())  # result.group() 查看结果
else:
    print('匹配失败')

匹配单个字符

代码

功能

.

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

[]

匹配[]中列举的字符

\d

匹配数字,即0-9

\D

匹配非数字,即不是数字

\s

匹配空白,即空白,tab键

\S

匹配非空白

\w

匹配非特殊字符,即a-z,A-Z,0-9,_,汉字

\W

匹配特殊字符,即非字母,非数字,非汉字

# ---匹配单个字符------
import re

# 字母,匹配特定的字母
# result = re.match('hello', 'hello world')
# .匹配任意的非换行字符
# result = re.match('hello.', 'helloworld')
# [] 匹配括号中的任意一个字符
# []
# result = re.match('hello[ab]', 'helloaworld')
# \d 0,1,2,3,4,5,6,7,8,9  [0-9]
# result = re.match('hello[a-z]', 'hellocworld')  # 能匹配到a到z的字母
# result = re.match('hello\d', 'hello0world')  # 能匹配到a到z的字母
# \s 空白字符  空格 tab键
# result = re.match('hello\s.', 'hello world')  # 能匹配到a到z的字母
# \w a-z A-Z 0-9  _汉字
result = re.match('hello\w', 'hello你world')  # 能匹配到a到z的字母
if result:
    print(result.group())
else:
    print('匹配失败')

匹配多个字符

# ----------匹配多个字符------------
import re

# *前边一个字符出现任意次--或者这样写
# result = re.match(".", 'hello world')
# result = re.match(".*", 'hello world')  # 默认尽量多的匹配
# result = re.match(".*w", 'hello world')
# ? 前边一个字符出现0次或者是1次
# result = re.match("hl?", 'hello world')
# result = re.match("he{0,1}", 'hello world')
# + 至少出现一次
result = re.match("hel+o", 'hello world')
# {m} 出现m次
result = re.match(".{3}", 'hello world')
# {m,n}出现m到n次
result = re.match(".{3,6}", 'hello world')
if result:
    print(result.group())
else:
    print('匹配失败')

匹配开头和结尾

代码

功能

^

匹配字符串开头

$

匹配字符串结尾

# 匹配开头和结尾
import re

result = re.search("\d.*", "hello 3 world")
# ^以什么开头
# result = re.search("^\d.*", "hello 3 world")
# $以什么结尾
result = re.search("\d.*$", "hello 3 world")
# [^]出了这些内容外,都匹配
result = re.search("^[^aeiou].*", 'hello 3 world3 a')
result = re.search("^[aeiou].*", 'ahello 3 world3 a')
if result:
    print(result.group())
else:
    print('匹配失败')

匹配分组相关正则表达式

代码

功能

|

匹配左右任意一个表达式

(ab)

将括号中字符作为一个分组

\num

引用分组num匹配到的字符串

(?P<name>)

分组起别名

(?P=name)

引用别名为name分组匹配到的字符串

# -----------匹配分组-------------
import re

# |
# result = re.match("163|qq|sina", "163.com")
# result = re.match("163|qq|sina", "qq.com")
# result = re.match("163|qq|sina", "sina.com")
# 分组,() 括号括起来的内容是一组,想要那一部分的数据,就可以给这部分数据的正则加括号
# result = re.match("(163|qq|sina).com", "163.com")
# result = re.match("(163|qq|sina).com", "qq.com")
# result = re.match("(163|qq|sina).com", "sina.com")
# result = re.match("(.*)@(163|qq|sina).com", "nshuling@sina.com")
# 正则中 点 可以匹配任意一个字符,如果匹配单个字符 . ,那么在正则中需要使用转义 \.
# 引用分组 \num
# 案例,匹配, HTML 双标签
# result = re.match("<[a-zA-Z0-9]{1,} .*<[a-zA-Z0-9]{1,}>", "<html> hello </hello>")
# # # 解决方案一:\1 在字符串中\ 是转义字符 \1 将 1进行转义
# result = re.match("<([a-zA-Z0-9]{1,})>.*</\\1>", "<html> hello </html>")
# # result = re.match("<([a-zA-Z0-9]{1,}) .*</\\1>", "<html> hello </div>")
# # 解决方案二:使用原生字符串
# result = re.match("<([a-zA-Z0-9]{1,})>.*</\1>", "<html> hello </html>")
# 解决方案三:给引起名字
result = re.match("<(?P<tag>[a-zA-Z0-9]{1,})>.*</(?P=tag)>", "<html> hello </html>")
if result:
    print(result.group())
else:
    print('匹配失败')

10.题目练习

  1. 题目一:有学生类,Student,类中存在私有属性,name和age:

  1. 要求:

  • 使用装饰器的方式定义name属性的property属性

  • 使用类属性的方法定义age属性的property属性

  • 使代码可以完整的运行

class Student(object):
    def __init__(self, name, age):
        self.__name = name
        self.__age = age

    @property
    def get_name(self):
        return self.__name

    @get_name.setter
    def set_name(self, name):
        self.__name = name

    # 定义属性
    def get_age(self):
        return self.__age

    # 设置属性
    def set_age(self, age):
        self.__age = age

    age = property(get_age, set_age)


if __name__ == '__main__':
    # 创建对象
    student = Student('小白', 13)
    print(student.age)
    student.age = 14
    print(student.age)
    # 调用名字
    print(student.get_name)
    student.set_name = '小黄'
    print(student.get_name)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

最初的梦10

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值