大家好,今天我们要解答,python能进行数据分析的案例 利用python进行数据分析案例,现在让我们一起来看看吧!
python高级编程
函数式编程
生成器
由于列表的容量是有限制的,所以需要一边循环一边计算后面的元素,这样的机制称为生成器:generator 创建生成器
import time
# 列表生成式
# list1 = [1,2,3,4,5,10]
list1 = [x for x in range(1,10)]
print(list1)
# 引出生成器:里面是一个对象,保存了产生元素的算法,同时会记录游标的位置
# 创建一个生成器:1.通过列表生成式来创建;
# 2. 通过函数来创建生成器(yield)
# 遍历生成器中的元素内容:
# 1. 通过next(g),当已经遍历生成器结尾,会抛异常StopIteration
# 2. 通过for循环来遍历
# 3. 通过object对象内置的__next__(),当已经遍历生成器结尾,会抛异常StopIteration
# 4. 调用send函数,但是生成器的第一个值必须使用send(None),后面的值就没有限制
g = (x for x in range(1,10))
print(g)
# print(next(g))
# print(next(g))
# print(next(g))
# time.sleep(5)
# print(next(g))
# print(next(g))
# print(next(g))
# print(next(g))
# for i in g:
# print(i,'----')
# g2 = (x for x in range(10) if x % 2 == 0)
# print(next(g2))
# print(next(g2))
# print(next(g2))
# print(next(g2))
# print(next(g2))
# print(next(g2)) #第六次next的时候,生成器中已经没有数据了
# 生成斐波那契数列生成器
def test1(times):
# 初始化
a,b = 0,1
n = 0
# print('a=',a,'b=',b)
while n < times:
# print('b=',b) # b就是斐波那契数列中的一个元素
yield b # yield一般用于创建生成器:返回后边的变量值给生成器
a,b = b,a+b
n += 1
return 'done'
# print(test1(6))
g3 = test1(6)
print(g3)
print(next(g3))
def test2():
# 初始化
a,b = 0,1
while True:
# print('b=',b) # b就是斐波那契数列中的一个元素
yield b # yield一般用于创建生成器:返回后边的变量值给生成器,yield 没有返回值
# temp = yield b
a,b = b,a+b
# print(temp) #输出 None
return 'done'
g4 = test2()
print(g4)
# print(next(g4))
# print(next(g4))
# print(next(g4))
# print(g4.__next__())
# print(g4.__next__())
# print(g4.__next__())
print((None))
print((''))
print((''))
print((''))
print((''))
print((''))
print((''))
生成器的特点:
节约内存迭代到下一次的调用时,所使用的参数都是第一次所保留下来的,在整个所有函数调用的参数都是第一次所调用时保留的,而不是新创建的
迭代器
迭代是访问集合元素的⼀种⽅式python爬取网页内容的过程。迭代器是⼀个可以记住遍历的位置的对象。迭代器对象从集合的第⼀个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。 迭代器:Iterator,可以被next()函数调用并不断返回下一个值的对象称为迭代器。 可迭代对象:Iterable,能够通过for循环来遍历里面的元素的对象
所以可作用于 for 循环的对象都是 Iterable 类型;可作用于 next() 函数的对象都是 Iterator 类型,它们表示一个惰性计算的序列;集合数据类型list 、 dict 、 str 等是 Iterable 但不是 Iterator ,不过可以通过 iter() 函数获得⼀个 Iterator 对象。
from import Iterable
from import Iterator
# 可迭代对象:Iterable,能够通过for循环来遍历里面的元素的对象
a = (1,)
b = [1,2]
c = {}
def test1(arg):
if isinstance(arg,Iterable):
print('arg对象是可迭代对象')
else:
print('arg对象不是可迭代对象')
def test2(arg):
if isinstance(arg,Iterator):
print('arg对象是迭代器')
else:
print('arg对象不是迭代器')
# test1(a)
# test1(10)
# test1('asd')
#
# test2(b)
# test2(10)
# test2('asd')
# test2((1 for x in range(5)))
# 把list,dict,str变成迭代器
test2(iter(b))
高阶函数
函数式编程的一个特点就是,允许把函数本身作为参数传入另一个函数,还允许返回一个函数! 高阶函数:将函数作为参数,传给另一个参数就是高阶函数
# 定义一个函数,传入一个列表[1,2,3,4,5,6,7],返回一个新的列表[原列表每个数字的阶乘][1!,2!,3!,4!,5!,6!,7!]
# 已经存在一个阶乘函数
def test1(num):
if num == 1:
return 1
else:
return num * test1(num-1)
# test2就是高阶函数,它的参数其中第二个参数是函数本身
def test2(num_list,func):
new_list = []
for x in num_list:
new_list.append(func(x))
return new_list
list1 = [1,2,3,4,5,6,7]
print(test2(list1,test1))
python内置的高阶函数
# 1. map:把一个可迭代对象中的每个元素转换成一个新的对象,最后返回一个迭代器
list1 = [1,2,3,4,5,10,6,8,20,4]
it1 = map(lambda x:x**2,list1) # x是列表中的每个元素
# print(it1.__next__())
# print(next(it1))
print(list(it1))
# 2. reduce:把一个可迭代对象中每个元素做聚合处理,最后返回一个聚合之后的值
from functools import reduce
print(reduce(lambda x,y:x+y,list1)) # 累加
def getmax(x,y):
if x > y:
return x
else:
return y
print(reduce(getmax,list1)) # 当前列表中的最大值
# 3.filter 把一个可迭代对象中的元素做过滤操作,如果func返回值为True则留下,否则过滤掉
emps = [# 员工列表
{'name':'zhangsan','age':18,'salary':3000},
{'name': 'lisi', 'age': 28, 'salary': 1000},
{'name': 'wangwu', 'age': 38, 'salary': 6000}
]
# 需求,请过滤留下大于18岁的员工,返回一个迭代器
print(list(filter(lambda x:x['age'] > 18,emps)))
# 4. max和min
# 计算薪资最高的员工
print(max(emps,key=lambda x:x['salary']))
# 计算薪资最少的员工
print(min(emps,key=lambda x:x['salary']))
# 5.sorted:把一个可迭代对象里面的每个元素做排序,返回一个列表
# 根据员工的年龄降序排序
print(sorted(emps,key=lambda x:x['age'],reverse=True))
匿名函数
匿名函数,顾名思义就是没有名字的函数
func = lambda x,y: x+y
print(func(10,20))
使用匿名函数的好处 对于比较单行返回的函数,使用 lambda 表达式可以省去定义函数的过程,让代码更加简洁,针对不需要多次复用的函数,使用 lambda 表达式可以在用完之后立即释放,提高程序执行的性能。而且还能配合其他的一些高阶函数配合使用
返回函数的高阶函数
def get_sum(*args):
def tt(): # 定义函数
sum=0
for n in args:
sum += n
return sum
return tt # 返回函数
f1 = get_sum(1,2,3,4,5,6)()
# print(f1)
# 需求:得到所有的素数(质数),打印小于100的所有质数
# 1.质数:最小的质数是2,
# 2.偶数都不是质数(0,2除外),只有1后面的奇数才有可能是质数
# 3. 思路:先得到所有大于1的奇数---》生成器,再把生成器中的所有元素过滤,去掉可以被小于元素本身的质数整除的
def odd_num():# 得到所有大于1的奇数的生成器
n = 1
while True:
n+=2
yield n # n就是大于1的所有奇数
g1 = odd_num()
# print(next(g1))
# print(next(g1))
def myfilter(num): # 判断是否能够整除的函数,num代表从一个生成器得到的一个数字(质数)
return lambda x:x%num > 0 # x其实是某一个奇数,n是小于x的一个质数
def tt(): # 创建一个质数的生成器,最小的质数是2
yield 2
g = odd_num() # 得到所有大于1的奇数
while True:
x = next(g) # 从生成器中拿到一个奇数
g = filter(myfilter(x),g) # 过滤之后再赋值给g
yield x
for n in tt():
if n < 100:
print(n)
else:
break
闭包
内部函数对外部函数作⽤域⾥变量的引⽤(⾮全局变量),则称内部函数为闭包 闭包的条件:
必须有一个内嵌函数内嵌函数必须引用一个定义在闭合范围内变量–内部函数引用外部变量外部函数必须返回内嵌函数
# 1. 闭包的定义
def fun_a(number_a): # 高阶函数,返回一个函数
def fun_b(number_b):
print(f'内嵌函数fun_b的参数是{number_b},外部函数fun_a的参数是{number_a}')
return number_b+number_a
return fun_b
result = fun_a(10) # 10传给fun_a的
# print(result(10)) # 10传给fun_b的
# print(result(20)) # 20传给fun_b的
# 2.闭包的应用
def create_line(a,b):
def line(x):
return a*x+b
return line
# 得到一个一元线性函数
l1 = create_line(2,2)
l2 = create_line(1.5,-2)
# 计算在线1中,当x=5时,对应的y
y = l2(5)
# print(y)
# 3.闭包里面修改外部变量的值
def test1():
# count其实不是局部变量,是介于全局变量和局部变量之间的变量,nonlocal标识
count = 1
def add():
nonlocal count
print(count)
count+=1
return count
return add
# print(test1()())
# 4.闭包的陷阱
def test3():
func_list = []
for i in range(1,4):
def test4(_i = i):
return _i**2
func_list.append(test4)
return func_list
f1,f2,f3 = test3()
print(f1(),f2(),f3())
装饰器
装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。 它经常用于有以下场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景。装饰器是解决这类问题的绝佳设计
def test1(func): # 定义一个额外的功能(装饰器)
def test2():
print('帮你把饭做好')
func()
print('洗碗')
return test2
@test1 # 装饰器
def eat():
print('我正在吃饭')
# eat=test1(eat)
eat()
print(eat.__name__) # test2
functools模块里面的wraps函数解决了重写了函数的名字和注释文档的问题 这个装饰器的功能就是不改变使用装饰器原有函数的结构
from functools import wraps
def test1(func): # 定义一个额外的功能(装饰器)
@wraps(func) # 使用func来包装test2
def test2():
print('帮你把饭做好')
func()
print('洗碗')
return test2
@test1 # 装饰器
def eat():
print('我正在吃饭')
# eat=test1(eat)
eat()
print(eat.__name__) # eat
带参数的装饰器
from functools import wraps
import time
def main_log(log_file=''):
def logger(func):
@wraps(func)
def write_logging(*args,**kwargs):
log = f'[info]:--时间是:{time.strftime("%H:%M:%S",time.localtime())}'
print(log)
with open(log_file,'a+') as f :
f.write(log+'\n')
func(*args,**kwargs)
return write_logging
return logger
@main_log() # 使用装饰器来给所有的work增加记录日志的功能
def work():
print('我在工作')
@main_log('') # 使用装饰器来给所有的work增加记录日志的功能
def work2(name,name2): # 1.当前work2函数可能有多个参数2.自定义日志文件的名字和位置,级别
print(f'{name}和{name2}在工作')
work()
work2('张三','李四')
使用类作为装饰器
from functools import wraps
import time
# 不使用函数,而是使用类做装饰器
class Logs:
def __init__(self,log_file='',level='INFO'):
self.log_file = log_file
self.level = level
def __call__(self, func): # 来定义装饰器的,需要有一个接收函数
@wraps(func)
def write_logging(*args, **kwargs):
log = f'[{self.level}]:--时间是:{time.strftime("%H:%M:%S", time.localtime())}'
print(log)
with open(self.log_file, 'a+') as f:
f.write(log + '\n')
func(*args, **kwargs)
return write_logging
@Logs() # 使用装饰器来给所有的work增加记录日志的功能
def work():
print('我在工作')
@Logs(log_file='',level='WARNING') # 使用装饰器来给所有的work增加记录日志的功能
def work2(name,name2): # 1.当前work2函数可能有多个参数2.自定义日志文件的名字和位置,级别
print(f'{name}和{name2}在工作')
work()
work2('张三','李四')
偏函数
functools.partial 的作用就是,把一个函数的某些参数给固定住(也就是设置默认值),返回一个新的函数,调用这个新函数会更简单。
import functools
print(int('123')) # 默认按照十进制进行转换
# print(int('123',base=16)) # 291 按16进制转换成10进制
# print(int('123',16)) # 291
def int_2(num,base=2):
return int(num,base)
print(int_2('1001'))
int_2 = functools.partial(int,base=2) #偏函数
print(int_2('1000000'))
面向对象进阶
正常情况下,当我们定义了一个class,创建了一个class的实例后,我们可以给该实例绑定任何属性和方法,这就是动态语言的灵活性。先定义class:然后尝试给实例绑定一个属性,还可以绑定一个方法,但是一个实例方法对另一个实例不起作用,那就得给类整个类绑定一个方法或属性,这样所有的实例都可以调用需要注意的是我们的动态语言在运行后还能修改的,但是静态语言是不可以的,这就会造成不严谨。 动态语⾔:可以在运⾏的过程中,修改代码 静态语⾔:编译时已经确定好代码,运⾏过程中不能修改
slots
为了达到限制的目的,Python允许在定义class的时候,定义一个特殊的 slots 变量,来限制该class能添加的属性 需要注意一点的是:使⽤ slots 要注意, slots 定义的属性仅对当前类实例起作⽤,对继承的⼦类是不起作⽤的
import types
class Person():
def __init__(self,name,age):
= name
= age
# 限制类动态增加属性
class Student(object):
# 只允许当前Student拥有name和sex属性
__slots__ = ('name','sex')
if __name__ == '__main__':
p = Person('张三',18)
# 1. 可不可以动态的给对象p赋予一个成员属性
Person.address = '北京'
p.sex = '男'
# 2. 可以给当前对象p动态的赋予一个新的成员(对象)函数吗
def run(self,work):
print(f'{}正在完成的工作是:{work}')
p.run = types.MethodType(run,p) #给对象p添加一个实例(对象,成员)函数
p.run('学习')
# 3. 给Person动态的赋予一个类函数
@classmethod
def class_run(cls,work):
print(f'类函数中的work是{work}')
= class_run
p.work('学python')
# 4. 给Person类动态赋予一个静态函数
@staticmethod
def static_run(work):
print(f'静态函数中的work是{work}')
Person.static_run = static_run
p.static_run('学习全栈')
Person.static_run('学习全栈')
# 验证__slots__
s = Student()
s.name = 'lisi'
s.sex = '女'
# s.age = 18
print(s.sex)
@property
@property 装饰器就是负责把一个方法变成属性调用的 @property 的实现比较复杂,先观察使用。把一个getter方法变成属性,只需要加上 @property 就可以了,此时, @property 本身又创建了另一个装饰器 @age.setter ,负责把一个setter方法变成属性赋值,于是,我们就拥有一个可控的属性操作
class Person(object):
# age属性的值限制的范围是0-88
def get_age(self):
return self.__age
def set_age(self,value):
if value >=0 and value <= 88:
self.__age = value
else:
# print('age的值必须在0-88之间')
self.__age = 0 # 0为age的初始值
raise ValueError('age的值必须在0-88之间')
class Person_Property(object):
# age属性的值限制的范围是0-88
@property # age属性暴露出去
def age(self):
return self._age
@age.setter # 当前age属性可以允许赋值
def age(self,value):
if value >=0 and value <= 88:
self._age = value
else:
# print('age的值必须在0-88之间')
self._age = 0 # 0为age的初始值
raise ValueError('age的值必须在0-88之间')
@property
def name(self):
self._name = '张三'
return self._name
if __name__ == '__main__':
# p = Person()
# p.set_age(18)
# print(p.get_age())
# p.set_age(100)
# print(p.get_age())
p = Person_Property()
p.age = 18
print(p.age) # age属性是可以读也可以写
# p.age = 100
# p.name = '李四'
print(p.name) # name属性是只读的
多重继承
class Father(object):
def work(self):
print('父亲在工作')
class Mother(object):
def work(self):
print('母亲在工作')
class Child(Mother,Father): # 多继承
def __init__(self,name):
= name
def work(self):
print('自己在工作')
if __name__ == '__main__':
c = Child('张三')
c.work() #如果多个父类中都有同样的函数,按照优先级来调用
print(Child.__mro__) # 打印Child类的继承结构,并且按照优先级
定制类
看到类似 slots 这种形如 xxx 的变量或者函数名就要注意,这些在Python中是有特殊用途的。 Python的class中还有许多这样有特殊用途的函数,可以帮助我们定制类
class Person(object):
def __init__(self,name):
= name
# 菲波那切数列前两个值是固定的
self.a,self.b = 0,1
# 用于定制对象的描述信息
def __str__(self):
return f'Person object (name : {})'
# person 默认不是可迭代对象,变成一个可迭代对象,返回一个迭代器
def __iter__(self): # 生成一个斐波那契数列
return self
# person 就变成一个迭代器了
def __next__(self):
self.a,self.b = self.b,self.a+self.b # 结算下一个值
if self.a > 1000: # 如果出现一个大于1000的数字,退出循环
raise StopIteration
return self.a
# person就可以类似于list
def __getitem__(self, item): # item可能是一个下标,还有可能是一个切片(范围)
if isinstance(item,int): # item是一个下标
a,b = 1,1
for x in range(item):
a,b = b,a+b
return a
elif isinstance(item,slice):# item是一个范围
start = item.start
stop =
if start is None:
start = 0 # start默认值
a,b = 1,1
l = []
for x in range(stop):
if x >= start:
l.append(a)
a,b = b,a+b
return l
# 当访问person对象中不存在的属性和函数的时候会抛出AttributeError,如果不想看到这个error则需要重写
def __getattr__(self, item):
if item == 'age':
print(f'{item}名字错误')
return 18
elif item == 'eat':
return lambda : print('eat()函数执行')
def __call__(self, *args, **kwargs):
print('person对象可以作为函数调用')
if __name__ == '__main__':
p = Person('张三')
print(p)
for n in p:
print(n)
# p 有点类似于一个list,在列表中还可以分片
print('下标为5的值是',p[5])
print('下标为5-10的值是',p[5:10])
print(p.age)
p.eat()
p() # 把person对象当成一个函数,直接调用,person对象=一个函数
print(callable(p)) # 判断出来p对象是不是可以调用的对象(函数)
通过 callable() 函数,我们就可以判断一个对象是否是“可调用”对象。
枚举类
from enum import Enum
# 当项目中需要使用12个月份时,
# Jan = 1
# Feb = 2...
# 枚举中:一个名字 对应一个值,第一种:定义一个枚举,用的多一些
Month = Enum('Month',('jan','feb','mar','apr','may','jun','jul'))
# 把整个枚举中的所有值遍历出来
print(Month.__members__) # 枚举中的值自动从1开始,不会出现重复
# 得到二月份的值
print(Month['feb'].value)
# 根据值得到月份的名字
print(Month(2).name)
# 定义一个颜色的常量,枚举
class Color(Enum): # 第二种:自定义一个枚举类
red = 100
green = 200
blue = 300
yellow = 200 # 不允许key相同或者value,如果value重复了,根据value取name,只能取到第一个
print(Color(200))
元类
class的定义是运行时动态创建的,而创建class的方法就是使用 type() 函数 type() 函数既可以返回一个对象的类型,又可以创建出新的类型,比如,我们可以通过 type() 函数创建出Hello 类,而无需通过 class Hello(object)… 的定义 除了使用 type() 动态创建类以外,要控制类的创建行为,还可以使用metaclass,也就是元类 动态创建类
# 第一种:引入模块需要模块的路径
# from 引入模块之后,就动态的创建了一个Person类,本质上python解释器自动调用了type
# from 面向对象进阶.元类 import Person
# def func(self, s='hello'):
# print(f'我说:{s}')
# 第二种: 使用type函数创建一个Person类,其实可以创建任何一个类型
# Person = type('Person',(object,),dict(say = func))
# 第三种:使用一个metaclass来创建一个Person类
class PersonMetaClass(type): # 所有的元类必须继承type
def __new__(cls, name,bases,attrs):
def func(self, s='hello'):
print(f'我说:{s}')
attrs['say'] = func
return type.__new__(cls,name,bases,attrs)
# 根据上面的元类,创建一个person类,首先需要一个模具,然后再生产产品
class Person(object,metaclass=PersonMetaClass):
pass
p = Person() # 创建一个Person类的实例
p.say()
print(type(p)) # 把实例p的类型打印出来<class '面向对象进阶.元类.Person'>
print(type(Person)) # 把Person类的类型打印出来<class 'type'>,本质上就是打印创建Person类的元类
# type()是一个元类,解释器内置的最顶级的元类
a = 19
print(a.__class__.__class__) # 打印a变量的类型int,打印a变量的类型的类型(元类)
通过方法创建元类
# 第一种写法,通过函数替代元类
def upper_attr(class_name,class_parents,class_attrs):
# 遍历任何一个类中所有的属性,把非私有的属性名字改成大写
# 定义一个字典保存改完名字之后的属性集合
new_attrs = {}
for name,value in class_attrs.items():
if not name.startswith('__'): # 判断是否为:非私有的属性
new_attrs[name.upper()] = value
# 直接调用type来创建一个类
return type(class_name,class_parents,new_attrs)
#测试
class Emp(object,metaclass=upper_attr):
name = '张三'
acl = 5000
if __name__ == '__main__':
print(hasattr(Emp,'name')) # 判断Emp类中是否有名字为小写name的属性 False
print(hasattr(Emp,'NAME')) # 判断Emp类中是否有名字为大写NAME的属性 True
print(hasattr(Emp,'ACL')) # 判断Emp类中是否有名字为大写ACL的属性 True
自定义一个元类
# 第二种写法,自己定义一个元类
class UpperMetaClass(type):
def __new__(cls, class_name,class_parents,class_attrs):
# 遍历任何一个类中所有的属性,把非私有的属性名字改成大写
# 定义一个字典保存改完名字之后的属性集合
new_attrs = {}
for name, value in class_attrs.items():
if not name.startswith('__'): # 判断是否为:非私有的属性
new_attrs[name.upper()] = value
# 直接调用type来创建一个类
return type.__new__(cls,class_name, class_parents, new_attrs)
#测试
class Emp(object,metaclass=UpperMetaClass):
name = '张三'
acl = 5000
if __name__ == '__main__':
print(hasattr(Emp,'name')) # 判断Emp类中是否有名字为小写name的属性 False
print(hasattr(Emp,'NAME')) # 判断Emp类中是否有名字为大写NAME的属性 True
print(hasattr(Emp,'ACL')) # 判断Emp类中是否有名字为大写ACL的属性 True
正则表达式
概念
正则表达式是使用单个字符串来描述、匹配一系列符合某个句法规则的字符串
re模块
正则表达式的常用方法
import re
tel_l= '''
asjdh
呵呵
as54d5a4d4a6wd4
99966655541
asd878fef7e
ww117415464864
'''
tel_2 = '呵呵abc'
pattern = re.compile(r'1[3-9]\d{9}') # 编译正则表达式后,得到一个编译对象
result = pattern.search(tel_l) # search只会返回第一个匹配的结果,如果没有匹配成功,则返回None
print(result)
print(result.group(0)) # 返回第一个匹配结果
print((0))# 返回第一个匹配结果的下标
result2 = pattern.match(tel_2) # match函数是从第一个字符开始匹配,如果第一个字符不匹配,则返回None
print(result2.group(0))
正则表达式的写法
正则表达式的组件可以是单个的字符、字符集合、字符范围、字符间的选择或者所有这些组 件的任意组合。 正则表达式是由普通字符(例如字符 a 到 z)以及特殊字符(称为"元字符")组成的文字模式。
import re
one = 'as'
print(re.match('.',one).group())# .匹配任意单个字符
two = '8'
two_2 = 'Hello Python'
print(re.match('[0-9]',two).group())
# print(re.match('[1,2,3]',two).group())
print(re.match('[hH]',two_2).group())# 匹配大写或小写的h
three = '填空1号,发射陈宫'
print(re.match('填空\d',three).group())
print(re.search('\d',three).group())
表示字符
字符功能.匹配任意单个字符(不包括换行符)[ ]匹配字符集,区间中的集合,可匹配其中任意一个字符\d匹配数字,即0-9,可以表示为[0-9]\D匹配非数字,即不是数字,相当于 [^0-9]\s匹配空白字符,即 空格,tab键,相当于 [ \t\n\r\f\v]\S匹配非空白字符,相当于 [^ \t\n\r\f\v]\w匹配单词字符,即a-z、A-Z、0-9、_\W匹配非单词字符,即非数字、字母、下划线中的任意字符,相当于[^\w]
转移字符
import re
path = 'C:\\a\\b\\c' # 文件路径
print(path)
print(re.match('C:\\\\',path).group())
# 字符串前面使用r,代表python中的原生字符串
print(re.match(r'C:\\',path).group())
数量
边界
import re
# 练习5:匹配163的邮箱地址,用户名包含6-18个字符,可以是字母数字下划线,但是必须以字母开头
emails = '''
aaaa_____@as
'''
print(re.search('^[a-zA-Z]\w{5,17}@163\.com',emails,re.MULTILINE).group())
print(re.search('^[a-zA-Z]\w{5,17}@163\.com$',emails,re.MULTILINE).group())
# 取反
print(re.search('[^0-9]','1$'))
print(re.search('.*\\bBeiJing\\b','I Love BeiJing too'))#<re.Match object; span=(0, 14), match='I Love BeiJing'>
print(re.search('.*\\bBeiJing\\b','I Love BeiJingxi too'))#None
print(re.search('.*BeiJing','I Love BeiJingxi too'))#<re.Match object; span=(0, 14), match='I Love BeiJing'>
分组
import re
# 需求1:匹配从0到100的数字,包括100
print(re.match('[1-9]?\d$','08'))
print(re.match('[1-9]?\d$','18'))
print(re.match('[1-9]?\d+$','100'))
print(re.match('[1-9]?\d$|100','100'))
# 需求2:匹配网易邮箱,也可以是
emails = '''
aaaa_____@as
'''
print(re.search('^[a-zA-Z]\w{5,17}@(163|126).com$',emails,re.MULTILINE))
# 需求3:匹配标签<标签></标签>
print(re.search('^<[a-zA-Z0-9]+>\w*</[a-zA-Z0-9]+>$','<h1>hello</h1>'))
print(re.search('^<[a-zA-Z0-9]+>\w*</[a-zA-Z0-9]+>$','<h1>hello</div>'))# 非法标签
print(re.search(r'^<([a-zA-Z0-9]+)>\w*</\1>$','<h1>hello</div>'))# 非法标签
print(re.search(r'^<([a-zA-Z0-9]+)>\w*</\1>$','<h1>hello</h1>'))
print(re.search('^<[a-zA-Z0-9]+>\w*</[a-zA-Z0-9]+>$','<div>hello</div>'))
# 第二种写法,匹配一个网页的嵌套标签
line = '<div><p>hello</p></div>'
line2 = '<div><p>hello</h2></div>'
print(re.match(r'<(?P<n1>\w*)><(?P<n2>\w*)>.*</(?P=n2)></(?P=n1)>',line))
print(re.match(r'<(?P<n1>\w*)><(?P<n2>\w*)>.*</(?P=n2)></(?P=n1)>',line2)) # None
re模块的高级使用
import re
emails = '''
aaaa_____@as
'''
lst = re.findall('(^[a-zA-Z]\w{5,17}@(163|126).com$)',emails,re.MULTILINE)
for i in lst:
print(i[0])
# 需求:匹配一个数字,把匹配结果的数字+1返回
def add(result): # result表示匹配对象
str_num = result.group()
num = int(str_num)+1
return str(num)
print((r'\d+',add,'python= 188'))
line = 'hello, world, beijing.'
print(re.split(r'\W+',line))
# 切割字符串
print(re.split(r':|\s','info:xiaozhang 33 shandong'))
# 非贪婪模式,需求,把电话和电话的描述信息尽可能分开,只能用正则表达式
line2 = 'This is my tel:188-9999-6666'
result = re.match(r'(.+?)(\d+-\d+-\d+)',line2)
print(result.group(1))
print(result.group(2))
贪婪模式:Python里数量词默认是贪婪的, 总是尝试匹配尽可能多的字符 非贪婪模式:与贪婪相反,总是尝试匹配尽可能少的字符,可以使用"*","?","+","{m,n}"后面加上?,使贪婪变成非贪婪
内存管理
垃圾回收机制-引用计数
import sys
class TestObject(object):
def __init__(self):
print('当前对象已经被创建,占用的内存地址为:%s'%hex(id(self)))
a = TestObject()
print('当前对象的引用计数为:%s'%sys.getrefcount(a)) #2
b = a
print('当前对象的引用计数为:%s'%sys.getrefcount(a))#3
list1 = []
list1.append(a)
print('当前对象的引用计数为:%s'%sys.getrefcount(a))#4
# 减少
# del a
#print('当前对象的引用计数为:%s'%sys.getrefcount(b))
b = 1000
print('当前对象的引用计数为:%s'%sys.getrefcount(a))#3
list1.remove(a)
print('当前对象的引用计数为:%s'%sys.getrefcount(a))#2
垃圾回收机制-隔代回收
import sys,gc
import time
class TestObject(object):
def __init__(self):
print('当前对象已经被创建,占用的内存地址为:%s'%hex(id(self)))
def __del__(self):
print('当前对象马上被系统GC回收了')
gc.disable()# 不启用gc,python3中默认启用,
while True:
a = TestObject()
b = TestObject()
a.pro = b
b.pro = a
del a
del b
print(gc.get_threshold()) # 打印隔代回收的阈值
print(gc.get_count()) # 打印gc需要回收的对象的数量
time.sleep(0.2)
原文地址1:https://blog.csdn.net/qq_42385761/article/details/109848392
参考资料:python中用turtle画一个圆形 https://blog.csdn.net/SXIAOYAN_/article/details/140061099