Python基础

本文详细介绍了 Python 的基础知识,包括数据类型、变量使用、条件判断、循环语句等内容,并涵盖了字符串、列表、元组、字典和集合的操作方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

编码

一个字节byte 是8位bit

字符是由字节构成的。

utf8中:z=1byte=8bit=2`8二进制(0-255位)

不同编码,一个字符所占的字节不一样

ASCII码中,一个英文字母(不分大小写)占一个字节的空间,一个中文汉字占两个字节的空间

utf-8编码中,一个英文字符等于一个字节,一个中文(含繁体)等于三个字节

Unicode编码中,一个英文等于两个字节,一个中文(含繁体)等于两个字节。

终端命令

盘符:
重定向 即 转到其他位置:cd>文件名,把路径放进去
rd 删除空目录
rd 删除 不管是否为空的目录,会询问
del 删除文件
echo 内容 >文件名 创建一个放入内容的文件
ren 旧文件名 新文件名 重命名文件名
cls 清屏

Pycharm中python快捷键

单行注释 # XXXX (选中注释内容,ctrl+/ 快捷键).

多行注释 三个双引号 ‘’ 或单引号 ’ 框起来.

快速重复 ctrl+D

格式 = 两边加空格 ctrl+alt+L

向上或向下移动一行 alt+shift+向上/向下箭头

向上或向下移动一段代码块 ctrl+shift+向上/向下箭头

查看代码运行过程 指向对象(内存地址) http://www.pythontutor.com/

导入非Python标准库的类型:Alt+enter

一、Python 简介
  1. Python 由荷兰人 Guido van RossIM 吉多 范 罗苏姆发明.

  2. Python 的特点:是 一种解释性语言;是交互式语言;是面向对象语言;是初学者的语言;是跨平台的.

二、基础内容
1.命名规则

只能是数字、字母和下划线;开头不能是数字或空格;不能是Python的关键字严格区分大小写.

2.命名方式

a.变量名、函数名和文件名全小写,使用下划线连接,如:stu_name.

b.命名做到 顾名思义.

c.尽量避免和系统内置函数和类以及模块重名.

d.首字母大写用于类的命名.(大驼峰命名法).

注:汉字可以作为变量名,不建议用.

3. 数据类型

string、list 和 tuple 都属于 sequence(序列)

列表 list[ ] 用来存储多个数据,属于可变数据类型

元组 tuple( ) 用来存储多个数据,属于不可变数据类型

字典 dict{ } 用来存储多个数据 ,属于可变数据类型

集合 set{ } 用来存储多个数据,无序

4.变量的类型

字符串 str 单引号或双引号 属于不可变数据类型

整型 int 是数字

浮点型 float 小数型

布尔型 bool Ture False

复数型 complex

5.变量的使用

常量 字母要大写,用于区分变量

定义多个变量,初始值一样 n1=n2=n3=22

定义多个变量,初始值不一样 n1,n2,n3,=11,33,99 左右变量个数保持一致

变量的意义:对于重复使用的数据,可以定义为变量,可以提高代码的维护效率。

6.变量的删除

del 变量名

7.获取变量类型

type (变量名)

print(type (变量名))

#类型转换

str(xx) 转换为字符串类型 (字符串属于不可变数据类型)

int(xx) 转换为整型

float(xx) 转换为浮点型

8.输出语句
print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)
# sep:间隔符 输出值之间以定义的方式 间隔,默认是空格。
# end:输出完内容后,以什么方式结尾,默认是换行。
# file=sys.stdout:默认输出到控制台
# file = open("file1.text","w")  打开并写入到文件file1.text,w是写入的意思
# flash = True 打开文件刷新,提高文件读写速度
9.输入语句
#无论用户输入什么内容,接收的内容永远是字符串类型.
input(xx)
10.不同进制
#二进制:0b
a = 0b10
print(a)
2
# bin()

#八进制:0o
a = 0o10
print(a)
8
# oct()

#十进制:默认

#十六进制:0x
a = 0x10
print(a)
16  #1*16的1次方+0*16的0次方
# hex()
11.算术运算符
#  +-*/
#  ** 幂运算
#  // 整除
#  % (取余)取模运算

# 字符串和字符串之间只支持加法运算符,拼接两个字符串
print('hello'+'world')
helloworld
# 字符串和数字只支持乘法运算符,会将字符串重复多次
print('world'*3)
worldworldworld


12.赋值运算符
a += 1   # a+1之后再赋值给a
a -= 1   # a-1之后再赋值给a
a *= 1   # a*1之后再赋值给a
a /= 1   # a/1之后再赋值给a
a //= 1  # a//1之后再赋值给a
a %= 1   # a%1之后再赋值给a
a **= 1  # a**1之后再赋值给a

# * 表示可变长度
x,*y,z = 1,2,3,4,5,6
print(x,y,z)
1 [2, 3, 4, 5] 6

# 元组的赋值
a = 2,3  # a为元组 (2,3)
# 交换两个变量的值,使用第三个变量
a=1
b=2
c=a
a=b
b=c
2 1
# 交换两个变量的值,使用加减法交换(必须同时支持加减法)
a=a+b
b=a-b
a=a-b
2 1
# 交换两个变量的值
a,b=b,a
2 1


12.比较运算符
#  数字和字符串做 == 运算结果是false,除了 == 以外的逻辑运算时,会直接报错。

#  如果是两个字符串进行比较,会将每个字符都转换成对应的编码,然后逐一进行对比。
In [1]: str1='a' 
In [2]: str2='ABC'

# 将字符转换成为对应的编码  a对应的编码是97,A对应的编码是65
In [3]: str1 > str2
Out[3]: True
    
# 内置函数 ord(字符)  查看该字符的对应编码

# chr(编码)  查看编码对应的字符
14.逻辑运算符
# 与and 或or 非not

# 逻辑 与and 运算的短路问题 : 
# 只要遇到false,结果就是false,就会停止,取第一个为false的值
# 0的布尔值为false
# 如果所有运算数都是True,输出最后一个值

# 逻辑 或or 运算的短路问题 : 
# 只要遇到true,结果就是true,就会停止,取第一个为true的值
# 如果所有运算数都是false,输出最后一个值

#不管与 还是 或 为真为假 有值可取 就取第一个遇见的值
15.位运算

&:参与运算的两个值,如果两个相应位都为1,则该位的结果为1,否则为0

|:只要对应的二个二进位有一个为1时,结果位就为1

^:当两对应的二进位相异时,结果为1

~:对数据的每个二进制位取反,即把1变为0,把0变为1 。~x 类似于 -x-1

<<:运算数的各二进位全部左移若干位,由 << 右边的数字指定了移动的位数,高位丢弃,低位补0

>>:右移动运算符:把">>"左边的运算数的各二进位全部右移若干位,>> 右边的数字指定了移动的位数

负数二进制:python没办法表示,因为整数的长度是可变的,最高位不定

三.条件判断
1.if 语句 格式
if 要判断的条件:
        条件成立时,要做的事情
2.if else 语句 格式
 if 条件:
        满足条件时的操作
    else:
        不满足条件时的操作
3.if… elif… elif… else 语句 格式
if xxx1:
        事情1
    elif xxx2:
        事情2
    elif xxx3:
        事情3
else

# elif必须和if一起使用,否则出错 else 一般用在最后,即所有条件都不满足时使用
4. if 语句 嵌套
if i == 1:
	if j == 2:
		if y == 3:
			print('3')
5.注意事项
# 在Python中允许类似于 5<a<10 的写法,这种写法在很多编程语言里都是不允许的,需要使用逻辑与运算符进行连接。
a = 10
1<a<20  # True
11<a<20  # False

# 三元运算符
# 格式:变量 = 值1 if 条件 else 值2 当条件成立时把 值1 赋值给变量,条件不成立时把 值2 赋值给变量,其实就是对if...else 语句的一种简写。
a = 10
b = 30
if a > b:
    c = a
else:
    c = b
print('a和b两个数的较大值是%d'%c)
# 简写
a = 10
b = 30
c = a if a>b else b
print('a和b两个数的较大值是%d'%c)

6.自动类型转换

**提示:**在Python中,转换成为布尔值时,只有 0,"",'',None,(),{},[] 会被转换成为False,其他都会被转换成为True。

四.循环语句
1. while 循环
while 判断条件:
    代码块
 
# while...else...
count = 0
while count < 5:
   print (count, " 小于 5")
   count = count + 1
else:
   print (count, " 大于或等于 5")

2.for 循环
# for in 循环后面是 可迭代对象

sites = ["Baidu", "Google","Runoob","Taobao"]
for site in sites:
    if site == "Runoob":
        print("菜鸟教程!")
        break
    print("循环数据 " + site)
else:
    print("没有循环数据!")
print("完成循环!"
break# 跳出循环体,结束了
continue# 跳出循环块中的剩余语句,开始新的循环
五.字符串:不可变数据类型
1.字符串常见操作
字符串的常见操作包括:

# 获取长度:len
# 查找内容:find,index,rfind,rindex

 #判断:
startswith,endswith,
isalpha, 判断是否是字符
isdigit, 判断是否是数字
isalnum, 判断是否定是数字字母组合,文字也会返回True
isspace
计算出现次数:count
替换内容:replace

# 切割字符串:
split:默认根据 空格 进行切割
rsplit(从右边切),
splitlines,
partition,
rpartition(从右边切,将字符串分为3部分,以元组的形式存)

# 修改大小写:capitalize,title,upper(所有变为大写),lower(所有变为小写)

# 空格处理:
ljust(字符串不够指定的位数,默认用空格补齐),
rjust(字符串不够指定的位数,默认用空格补齐),
center(字符串不够指定的位数,字符两边默认用空格补齐),
lstrip(去除字符串左边的指定字符,默认是空格),
rstrip(去除字符串右边的指定字符,默认是空格),strip(去除字符串两边的指定字符,默认是空格)

# 字符串拼接:join (将列表拼接为字符串)
# 用'a'拼接(h a x a m a d a q)
print('a'.join('hxmdq'))  
#haxamadaq  把hxmd一个个取出,并在后面添加字符a. 最后的 q 保留,没有加 a

print('a'.join(['hi','hello','good']))  #hi a hello a good

txt = '_'
# 用'_' 拼接
print(txt.join(['hi','hello','good'])) #hi_hello_good
print(txt.join(('good','hi','hello'))) #good_hi_hello
# 调用方法格式
str.方法名()
注意:在Python中,字符串是不可变的!所有的字符串相关方法,都不会改变原有的字符串,都是返回一个结果,在这个新的返回值里,保留了执行后的结果!
2.字符串格式化
# 1. 使用%占位符:% s 字符串占位符,% d 整数占位符,% f 浮点占位符;
    %(变量名1,变量名2,...# ("姓名:%s","职位:%s","公司地址:%s" % (name, job, address))
# % 0 nd 不够n位 用 0 补齐
# % .n f 小数点后保留 n 位
# %% 表示一个普通的占位符
# % o/x  以8进制/16进制输出
# % c   将字符对应的字符编码输出

name = 'chris'
job = '讲师'
address = '上海市'
print('--------------------------------------')
print("姓名:%s","职位:%s","公司地址:%s" % (name, job, address))
print('-------------------------------------')   
#  输出
--------------------------------------
姓名:chris,职位:讲师,公司地址:上海市
------------------------------------- 
# 2. 使用字符串的format方法
name = 'zhangsan'
age = 18
print('我的名字是{},我今年{}岁'.format(name,age))
print('我的名字是{1},我今年{0}岁'.format(age,name))
print('{:03}'.format(8))    #008
print('{:.3}'.format(32.2222))    #32.2
print('{:.3f}'.format(32.2222))    #32.222

# 3. 使用 f 格式化字符串

print(f'我是{name:.2f}\n我今年{age}岁')   # 保留两位小数
# 我是zhangsan
# 我今年18岁

# 4.字符和编码的相互转化
# chr(获取编码对应的字符) 和 ord(获取字符对应的编码) 只对字符有效,无法使用于字符串

# 字符串的编码encode
字符串.encode(编码方式)

# 解码 decode
字符串.decode(编码方式)
六.列表
1.列表 list[] :容器,存放数据;(内容)可变数据类型
2.可存储的数据类型
  • 列表可以存储任意类型的数据。一个列表可以同时存储不同的数据。通常情况下,一个列表保存的数据是相同的类型。
  • 不同的数据类型在操作时,允许的方式是不同的。
  • 支持 加法+ (两个列表合并) 和 乘法* (将列表内容重复n次)
3.列表支持下标和切片

和字符串类似:从0 开始计数

list[3]: 取下标为3的数据,即第四个数据

list[3:7]:含3 不含7

4.列表的增删改查

append / extend / insert:

clear / remove / pop:

index -索引

1>.添加元素

  • list.appent(“天蓬元帅”) #在列表后面 添加元素

    # 直接使用append方法将字典添加到列表中,如果更改字典中的数据,那么列表中的内容也会发生改变,这是因为dict在Python里是object,不属于primitive type(即int、float、string、None、bool)。这意味着你一般操控的是一个指向object(对象)的指针,而非object本身。下面是改善方法:使用copy()
    info = {}
    inf = []
    for j in range(3):
        info['sid'] = s[j][0]
        info['name'] = s[j][1]
        info['score'] = s[j][2]
        j += 1
        inf.append(info.copy())
        # inf.append(info) 字典的内容改变,列表的内容也会改变
        print(info)
    print(inf)
    
    
    # 在列表末尾,追加另一个序列的多个值
    list.extend(["天蓬元帅","嫦娥","哪吒"])
    
    list = list + ["",""] 		#列表支持加法运算,可直接加元素
    
    list.insert(5,"哮天犬")		#在指定位置 插入元素
    

2>.删除数据

list.clear()		#用来清空列表
list.remove("哮天犬")		#删除指定数据
list.pop(5)		 #删除指定下标上的元素
del list[2]		#删除指定下标上的元素

3>.修改元素

  • list[5] = “如来佛祖” #直接使用下标修改指定下标上的元素

  • i = list.index(“七仙女”) #根据元素找对应位置

  • list[list.index(“七仙女”)] = “寿星公” #修改指定元素为某元素

5.遍历列表:拿列表中的每一个元素
monsters = ["","","","","","","","",""]

i  = 0
while i < len(monsters):
	print ( f '下标为{ i } 的元素是{monsters[ i ] } ‘ )
	i += 1
# 本质是调用可迭代对象的迭代器的next方法,不断获取下一个数据
for m in monsters:   
	print( m )
# 带下标的遍历
j = 0
for m in monsters:   
	print ( f '下标为{ j } 的元素是{monsters[ m ] } ‘ )
	j += 1

# 用来将一个可迭代对象添加序号。带下标的循环可以用enumerate
for j, m in enumerate(monsters):   
	print ( f '下标为{ j } 的元素是{monsters[m ] } ‘ )
nums = [6, 5, 3, 1, 8, 7, 2, 4]
# 1.sum ave
# sum = 0
# for i in nums:
#     sum += i
# ave = sum/len(nums)
# print(sum,ave)
# 2.求最大数和最小数以及位置
m_max = nums[0]    #假设第0个数是最大数
max_index = 0    #假设最大数的下标

m_min = nums[0]   #假设第0个数是最小数
min_index = 0    #假设最小数的下标

for i,m in enumerate(nums):
    if m_max < m:
        m_max = m
        max_index = i
    if m_min > m:
        m_min = m
        min_index = i
print(f'最大数是{m_max},下标是{max_index}\n最小数是{m_min},下标是{min_index}\n')
6.列表排序:冒泡排序???
7.列表中的排序和列表的翻转
list.sort()   # 可以直接调用sort方法排序,默认是升序
list.sort(reverse=Ture)  # 添加参数reverse=Ture,降序排列

list.reverse()   # 翻转  直接修改原有列表
new_list = list[::-1]   # 翻转  不修改原有列表
# 列表中嵌套字典 按字典的值排序,使用sorted函数
s = '01#张三#60-02#李四#90-03#王五#70'.split('-')

for i in range(3):
    s[i] = s[i].split('#')
print(s)    # 将字符串中按符号分割,
info = {}
inf = []
for j in range(3):   # 遍历列表,将列表中的内容以字典的形式存起来,
    info['sid'] = s[j][0]
    info['name'] = s[j][1]
    info['score'] = s[j][2]
    j += 1
    inf.append(info.copy())  # dict内容改变时 列表中的内容 也会改变 用copy 解决这个问题
    
# 按照列表中嵌套的字典的值进行排序,使用内置函数sorted,reverse = True 表示按照降序排列
inf_sort = sorted(inf, key=lambda e: e['score'], reverse=True)
print(inf_sort)
# sorted(列表名, key = lambda e:e['要排序的值']))  默认是升序
七. 元组tuple()
1. 不可变数据类型
# 不可增删改元组的数据
a = (1,2,3,4)
b = (5,6,7)
a.index(2)   # 返回指定元素的下标
print(a+b)   # 元组相加,返回新的元组
八.字典dict{}
1.基本使用

字典用来保存多个数据,是可变的数据类型(列表也是)

格式:dict{ key : value,… }

# 字典的 Key 必须是不可变的数据类型(字符串,整型,布尔值,元组() )
# 字典的 value 可以是任意类型,可以重复
# 字典的 key 重复出现 后一个出现的值会覆盖前一个值
# 字典是一个无序的容器
# 只能通过 key 获取指定的 value

d.key()		# 获取键
d.values()	# 获取值
d.get(key)  # 返回键对应的值

# dict.items()
d = {'age': '2', 'name': 'jane', 'sex': 'm'}
print(d.items())
# 输出
dict_items([('age', '2'), ('name', 'jane'), ('sex', 'm')])
# 列表嵌套元组[(key,value),...]
2.增删改查
# update :添加到指定字典dict里的字典。
d1={'place':'上海'}
d.update(d1)
# clear  清空 字典内容
# pop   根据 键删除对应的值
# popitem   删除最后一对键值对
3.字典遍历
# 取出 健为 k 的值 person[ k ]
for k in person.key:
	print(person[ k ])
4.字典的函数
# dict.fromkeys() 函数
# 用于创建一个新字典,以序列 seq 中元素做字典的键,value 为字典所有键对应的初始值
seq = ('name', 'age', 'sex')
 
dict = dict.fromkeys(seq)
print ("新的字典为 : %s" %  str(dict))
 
dict = dict.fromkeys(seq, 10)
print ("新的字典为 : %s" %  str(dict))

新的字典为 : {'age': None, 'name': None, 'sex': None}
新的字典为 : {'age': 10, 'name': 10, 'sex': 10}
九.集合set()

1.格式:x = { ‘name’,5,True} 或 set(‘name’,5,True)

  • 与字典的区别:字典是通过键值对保存数据,集合是保存单个的值

  • 与列表、元组的区别:

    • 集合保存的数据是无序的,存入的数据跟输出的顺序不同,不能通过下标获取数据

    • 集合不保存重复的数据,有重复的数据会自动去重

2.定义空集合:b = set( )

十.函数的使用
1.函数的参数

1.缺省参数:

位置参数:

关键字参数:通过变量赋值

*args :可变位置参数

**kwargs:可变关键字参数

global :全局变量。在函数内部修改全局变量

变量相关的内置函数:

globals 和 locals 和 vars

globals:用来获取所有的全局变量

locals:用来获取当前作用域的变量

vars:如果不传递参数,基本等价于locals。如果传入参数,会列出对象的属性

2.函数参数 高级

2.函数的返回值
3.函数的文档注释
4.变量的作用域
5.可变类型和不可变类型

可变数据类型 不建议 作为函数的参数使用;一定要使用,一定要默认为None

6.递归函数的使用
# 递归 就是 函数自己 调用 自己
# 递归一定要留好出口(停止的条件)
7.匿名函数

1.匿名函数的使用

# 用 lambda 关键词 创建小型匿名函数。
# 格式:lambda 参数列表: 运算表达式

2.使用场景

8.把函数当做参数使用
9.常用内置函数
  1. sorted:用来将一个 无序列表进行排序
num = (2,4,3,6,7,8)
x = sorted(nums)   #sorted 内置函数 不会改变原有的数据,而是生成一个新的有序的列表


sorted 语法:
sorted(iterable, key=None, reverse=False)  
参数说明:
iterable -- 可迭代对象。
key -- 主要是用来进行比较的元素,只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序。
reverse -- 排序规则,reverse = True 降序 , reverse = False 升序(默认)。
返回值
返回重新排序的列表。
s = '01#张三#60-02#李四#90-03#王五#70'.split('-')

for i in range(3):
    s[i] = s[i].split('#')
print(s)
info = {}
inf = []
for j in range(3):
    info['sid'] = s[j][0]
    info['name'] = s[j][1]
    info['score'] = s[j][2]
    j += 1
    inf.append(info.copy())  # dict内容改变时 列表中的内容 也会改变 用copy 解决这个问题

inf_sort = sorted(inf, key=lambda e: e['score'], reverse=True)
print(inf_sort)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-15cSkwUM-1628010512909)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210126110710374.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CxiD2yZo-1628010512911)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210126110805016.png)]

  1. map(f,list) 函数
#map()是 Python 内置的高阶函数,它接收一个函数 f 和一个 list,并通过把函数 f 依次作用在 list 的每个元素上,得到一个新的 list 并返回

10.高阶函数

1.函数可以作为另一个函数的返回值

2.函数也可以做为另一个函数的返回值

11.函数嵌套函数
12.装饰器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8s469xfi-1628010512912)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210126142708048.png)]

13. 其他内置函数
# 数学相关

1.abs:求绝对值

2.divmod:得到一个元组,第一个是商,第二个是余数

max / min / sum

pow(2,10,5):幂运算2的10次方模于5

round(3,1415892,2):四舍五入,保留指定位数

# 可迭代对象相关

1.all:判断一个可迭代对象的所有元素转为布尔值后 是否全是True

2.any:

iter :用来获取一个可迭代对象的迭代器

next :获取计算器的下一个数据

len:用来计算可迭代的长度

3.enumerate(可迭代对象,要返回的对象的索引的开始位置) :枚举,

x=[a,b,n,l,m]
enumerate(x,2)

返回:
2,a
3,b
4,n
5,l
6,m
#转换相关的

1.ascii():获取字符(串)的Unicode编码

2.ord():只能获取单个字符的Unicode编码

3.chr():获取编码对应的字符

4.bin / oct / hex / :转化为相应的进制

# 判断相关的

1.callable():判断一个对象是否能被调用

2.isinstance():判断一个对象是否是由指定类或它的子类创建的

3.issubclass():用来判断一个类是

# 操作对象相关的方法
# 未归类

dir():列出一个对象所有的方法和属性

eval():用来执行字符串里的python代码

repr():

exit():用来结束整个程序

quit():用来结束整个程序

globals():用来获取全局变量

locals():用来获取当前作用域里的变量

vars:不传参等于locals;传一个对象,会以字典的形式列出对象的所有属性

hash():

open():打开一个文件

十一. 内置模块

定义:遵守了命名规则的 py 文件就是一个模块

import xxx

1. import random # 生成随机数

常见方法

random.random    # 生成[ 0, 1 ) 的随机浮点数

random.randrange (a,b)  # 生成 [ a,b ) 的随机整数

random.randint(a,b)     # 生成 [ a,b ] 的随机整数

random.uniform(a, b)   # 生成 [ a,b ] 的随机浮点数

random.choice( 序列 )    # 从序列(一堆有序的数据)里随机取出一个元素

random.choices  (  序列 , k=5 )   # 在序列里选择 K 个数据,允许重复

random.sample( 序列 , 3)     # 从序列里随机取出指定个数的元素,不允许重复

random.shuffle ( 序列 )     #  让序列重新排序
2. import math
math.fabs(-100) # 取绝对值
math.factorial(5) # 计算阶乘  0的阶乘为1
math.ceil(34.01)  #向上取整
math.floor(34.98)  # 向下取整
math.pi  # π的值,约等于 3.141592653589793
math.pow(2, 10) # 2的10次方   求幂运算
math.sqrt(4)   # 开平方
math.sin(math.pi / 6)  # 正弦值  用弧度
math.cos(math.pi / 3) # 余弦值
math.tan(math.pi / 2)  # 正切值
3. os (operation system)模块
Windows => nt = newtechnology 和 (类)Unix  => posix
os.name   # 有两个值 nt 和 posix
os.sep   # windows 里用 \ ,非windows 用 /
# 在 winsows里,文件路径用 / ,或者 \\  或者 r'D:\千锋课程\4.Python'
os.getcwd()    # 获取当前的工作目录,即当前python脚本工作的目录
os.listdir()    # 列出指定目录里的所有文件和文件夹
os.chdir() # 切换路径.
#  os.chdir('../')   返回上一级

os.rename() # 重命名文件
os.remove()  #删除文件

os.mkdir()  # 新建文件夹
os.rmdir()   # 删除空文件夹
os.removedirs() # 删除空文件夹

os.path.exisit()  # 用来判断文件或文件夹是否存在,存在返回True,不存在返回False
os.path.isdir()   #用来判断路径对应的是否是个文件夹,存在返回True,不存在返回False
os.path.isfile()    #用来判断路径对应的是否是个文件,存在返回True,不存在返回False

os.path.splitext(path)  # 用来将指定路径进行分隔,可以获取到文件的后缀名
s
os.path.join(path,file_name)   #拼接文件路径

os.path.abspath(file_name)   # 获取文件的绝对路径
# 递归 在函数内部调用函数本身

4. import time
time.time()  # 获取从1970-01-01 00:00:00 UTC 到现在时间的秒数
time.strftime("%Y-%m-%d %H:%M:%S") # 按照指定格式输出当前日期时间
# 输出结果为
# 2021-01-28 19:04:51

time.strptime(f,格式)  # 按照指定格式输出
# 输出结果  类型是 类 :<class 'time.struct_time'>
time.struct_time(tm_year=2021, tm_mon=9, tm_mday=10, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=4, tm_yday=253, tm_isdst=-1)

# 该方法 表示 day1 是今年的第几天
day1.tm_yday 

time.asctime()  #Mon Apr 15 20:03:23 2019
time.ctime()  # Mon Apr 15 20:03:23 2019

time.sleep()   # 暂停程序多少秒
5. import datetime
# 获取当前时间
print(datetime.datetime.now())  

#当前 时间日期的 指定年份2020年
print(datetime.datetime.now().replace(year=2020))
#当前 年份 的指定 日期时间
print(datetime.datetime(year=now.year, month=9,day=10,hour=0,minute=0,second=0))

#当前日期时间的  下一周的时间 
#  与datetime.datetime.now() 相差一周的日期时间
print(datetime.datetime.now()+datetime.timedelta(weeks=1))  # 一周后的此时此刻 2021-02-10 20:19:17.540412

print(datetime.timedelta(weeks=1))  # 7 days, 0:00:00

# 当前时间与 要比较的时间 t 之间的天数days,秒数seconds,
now_time = datetime.datetime.now()
t = datetime.datetime(2021, 9, 10)
d = (t-now_time).days
s = (t-now_time).seconds


6.浅拷贝与深拷贝

copy:浅拷贝 ,修改copy后的数据,不影响原来的数据。只是拷贝内容,地址不一样。如果数据中 有 其他子列表或者其他嵌套,数据是指向该地址的,修改 其他子列表或者其他嵌套 的数据,原数据与copy后的数据内容都会改变。

deepcopy:深拷贝,所有的数据都是新的,指向新的地址,包括数据中其他子列表或者其他嵌套。修改 其他子列表或者其他嵌套 的数据,原数据不会改变

7. String模块
# ascii_letters:是生成所有字母,从a-z和A-Z
# digits:是生成所有数字0-9.
十二. 文件操作
1. 参数说明:
open(文件路径,打开方式,编码方式)

# 文件路径:相对路径,绝对路径

# 1. 相对路径:相对当前正在编辑的文件所在的文件夹
# ../:返回上一级
# ./:表示当前目录,是可以省略不写的

# 2. 绝对路径:
#第一种 加 r   :    r 'D:\千锋课程\4.Python\Day09-常见模块&文件操作\02-代码'
#第二种 加 \    :    'D:\\千锋课程\\4.Python\\Day09-常见模块&文件操作\\02-代码'
    
#指定打开文件的方式:r,w,a

# 文件的编码方式:encoding = utf8 / gbk / ...

2. 文件操作:打开、写入、追加、编码
#文件的打开方式:文本形式  和  二进制
# t :默认是以纯文本形式打开
# b :以二进制的形式打开文件
 
    
以下是以 字符 来操作文件内容:
# r / r+:以只读方式打开文件 / 以读写方式打开文件,文件的指针即光标会放在文件开头,如果文件不存在就会报错

# w / w+:以只写方式打开文件 / 以读写方式打开文件,如果文件存在会替换掉;如果文件不存在就会新建文件

# a / a+:以追加方式打开文件 / 以读写方式打开文件,文件存在的话,文件的指针即光标会放在文件结尾;如如果文件不存在就会新建文件


以下是以 字节 来操作文件内容:   ----一些文件必须用这种模式,比如 图片  音视频文件等
# rb / rb+ 以二进制形式打开文件用于只读 / 读写,文件的指针即光标会放在文件开头,如果文件不存在就会报错

# wb / wb+:以二进制形式打开文件用于只写 / 读写,如果文件存在会替换掉;如果文件不存在就会新建文件

# ab / ab+:以二进制形式打开文件用于追加 / 读写,文件存在的话,文件的指针即光标会放在文件结尾;如如果文件不存在就会新建文件

# 以二进制方式操作文件时,不用设置文件的编码方式


# 1.打开文件,如果不指定打开方式,默认是只读的形式打开

#r
f1 = open('text.txt','r')    # 以只读的形式打开



# w
f2 = open('text.txt','w') # 以写入的形式打开。只能写,不能读取。
f2.write()   # 如果文件不存在,会创建新文件。会覆盖之前的内容。

# a
f3 = open('te','a')   # 以追加的方式打开文件
f3.write()   # 如果文件不存在,会创建新文件。


# 2.操作文件(读或写)
content = f.read()    # 如果文件不存在,会报错。
content = f.read(10)   
       # read(n) 若以字节的形式打开文件, n 是读取字符的个数
       #         若以二进制打开文件,n 是读取的是字节的大小,单位是字节
f.readline()    # 读取一行数据
f.readlines()  # 读取所有行数据,把每一行数据当做元素存放在列表中,不会重复读取

f.write()
# 加 \n 换行,没有 \n 会在同一行显示数据
f.writelines('你好\n你好\n你好\n')   #按行写入文件。可写入列表,写入列表时,列表每一个元素当做一行
加 \n 输出如下:
你好
你好
你好
你好



# 3.关闭文件
f.close()

#  encoding 编码方式
f1 = open('text.txt','r',encoding = utf8)
# csv
3. 文件备份

4. 将文件写入到内存
python 提供了 StringIO 和ByteIO 两个类,将字符串和二进制数据写入到内存中
# Python 提供了 tringIO,BytesIO
from io import StringIO,BytesIO

#创建一个StringIO对象
sio = StringIO()
# 写
sio.write("hello")
sio.write('bye')
print(sio)
# 获取写入的数据  getvalue
data = sio.getvalue()
print(data)

#写入二进制数据
bio =BytesIO()
bio.write('hello'.encode('utf-8') )
# 获取数据   getvalue
data = bio.getvalue()
print(data)   # 二进制形式输出
print(data.decode('utf-8'))

5. 异常处理
try:   # 如果输入内容不满足条件 不报错,直接走except
    b = float(input('请输入一个小数'))
    print(b*2)
    
# except 可以给出多个
except Exception as e:
    print('输入的不合法')
except Exception as e:
    print('输入的不合法')
    
# Exception 指的错误类型:typeerror....
except TypeError as e:
    print('数据类型错误')

6. .序列化 反序列化
1.序列化:

将Python里的对象(比如列表、字典等)变成 二进制 或者 字符串(字节数据) 进行存储或者传输(跨平台或者跨语言)过程

2.反序列化:

将字符串或者二进制,加载成Python对象来使用的过程

3.两个模块用来实现数据的序列化和反序列化。

json模块:将对象转换成为字符串,可以跨平台传输。只有json里识别的数据类型才能被转换成json字符串

pickle模块:将对象转换成为二进制,不可以跨平台

4.json模块 将对象转换成为字符串将对象转换成为字符串
  1. dumps / dump

json.dumps:输出结果为字符串,可以包括字符串,必须用双引号括起来

json.dump:等价于 dumps + file.write( )

import json
name = ['lihanhan','mmkek','danaa']

# dumps 将对象转换成为字符串,不具备将数据写入到文件的功能
file = open('msg.txt')
x = json.dumps(name)
print(x)
# 输出:["lihanhan", "mmkek", "danaa"]

# dump  将对象转换成为字符串的同时,指定一f.个文件对象,把转换后的字符串写入到这个文件里
file = open('msg.txt','w')
y = json.dump(name,file)
print(y)

file.close()
  1. loads / load

json.loads( ):将字符串输出结果为Python对象,可以包括字符串,必须用双引号括起来

json.load:等价于 loads + file.write( )

# 
5.pickle模块:将对象转换成为二进制
十三. 面对对象基础
1. 面向对象 和 面对过程(C语言)
  • 面向过程:关注点在于怎么做

    • 把完成某一个需求的 所有步骤 从头到尾 逐步实现
    • 根据开发需求,将某些 功能独立 的代码 封装 成一个又一个 函数
    • 最后完成的代码,就是顺序地调用 不同的函数
  • 面向对象:面向对象编程的关注点在于谁来做

    相比较函数,面向对象是更大的封装,根据职责在 一个对象中封装多个方法

    • 在完成某一个需求前,首先确定职责 —— 要做的事情(方法)
    • 根据 职责 确定不同的 对象,在对象内部封装不同的方法(多个)
    • 最后完成的代码,就是顺序地调用不同对象的相应方法。
# 面向对象的三大特点:
1.封装
2.继承
3.多态
2. 类 / 对象 / 方法
1. 定义
  • :是对一群具有相同特征或者行为 的事物的一个统称。由 对象和方法组成
  • 特征:即是 对象。
  • 行为:即是 方法
2. 类和对象的关系

对象:是类的实例。由哪一个类创建出来的 对象,就拥有在哪一个类中定义的属性和方法。是内存里的一段内存空间。

  • 类是模板,对象是根据类这个模板创建出来的,应该先有类,再有对象。
  • 使用同一个类,能够创建出很多对象。
  • 类中定义了什么属性和方法,对象中就有什么属性和方法。
  • 不同对象对应的属性值也会不同。

例如:定义了一个狗类,这个狗类有以下属性:

品种 颜色 性别 名字

4. 类的设计

在程序开发中,要设计一个类,通常需要满足一下三个要素:

  1. 类名 这类事物的名字,安照大驼峰命名法(每个单词的首字母大写)起名。

  2. 属性 这类事物具有什么样的特征。

  3. 方法 这类事物具有什么样的行为。

5. 类的格式和 self
class 类名:
    def __init__(self,对象属性)#初始化方法
        pass
    def 方法1(self,参数列表):
        pass
    def 方法2(self,参数列表):
        pass
 # self:形参的作用,占位。通常 是写 self.
6. 魔术方法:

Python 的类里提供的,两个下划线开始,两个下划线结束的方法,就是魔法方法

创建对象后,python解释器默认调用__init__()方法,初始化方法

而当删除对象时,python解释器也会默认调用一个方法,这个方法为__del__()方法。

1. 构造方法:init

__init__():构造方法,设置对象的属性

class Person:

    def __init__(self, name, weight):
        self.weight = weight
        self.name = name

注意

__init__()方法在创建对象时,会默认被调用,同时设置对象属性,不需要手动的调用这个方法。

__init__()方法里的self参数,在创建对象时不需要传递参数,python解释器会把创建好的对象引用直接赋值给self

在类的内部,可以使用self来使用属性和调用方法;在类的外部,需要使用对象名来使用属性和调用方法。

如果有多个对象,每个对象的属性是各自保存的,都有各自独立的地址。

方法是所有对象共享的,只占用一份内存空间,方法被调用时会通过self来判断是哪个对象调用了实例方法。

2. str

__str__() :我们在打印一个对象时,可能需要列出这个对象的所有属性。

class Cat:
    def __init__(self,name,color):
        self.name = name
        self.color = color

tom = Cat('Tom','white')
# 使用 print 方法打印对象时,会调用对象的 __str__ 方法,默认会打印类名和对象的地址名
print(tom)   # <__main__.Cat object at 0x0000021BE3B9C940>

# 没有找到str时  调用repr

# 我们在打印一个对象时,可能需要列出这个对象的所有属性
# 选择重写__str__方法
class Student:
    def __init__(self,name,score):
        self.name = name
        self.score = score
    def __str__(self):
        return '姓名是:{},成绩是{}分'.format(self.name,self.score)

s = Student('lisi',95)
print(s)   # 姓名是:lisi,成绩是95分
3. 析构方法:del

__del__方法:析构方法,当对象被销毁时调用的方法.

7. 身份运算符

is:身份运算符 is 来判断两个实例对象是否完全是一个对象。判断的是两个对象所在的内存地址 即 id 是否一致

  1. 判断两个对象 相等

法1:判断内存地址(id),用 is 判断

法2:判断值是否相等:== 本质上是调用对象的 eq 方法

做等于运算时会调用 eq方法, 如果没有eq方法,默认比较内存地址

做不等于运算时会调用ne方法, 如果没有ne方法找eq方法,都没有,就报错

class Person:
    def __init__(self,name,age):
        self.name = name
        self.age = age

p1 = Person('张三',18)
p2 = Person('张三',18)
print(p1 == p2)  # False
  1. 判断两个对象不等

法:调用 gt 方法 / lt 方法

做大于>运算时会调用 gt 方法, 如果没有gt方法,会找lt方法取反;如果没有lt会报错

做大于>运算时会调用 gt 方法, 如果没有gt方法,会找lt方法取反;如果没有lt会报错

十四. 面对对象 高级
1. 私有属性和方法

在实际开发中,对象的某些属性或者方法可能只希望在对象的内部使用,而不希望在外部被访问到,这时就可以定义私有属性和私有方法

定义方法:在定义属性或方法时,在属性名或者方法名前增加两个下划线__,定义的就是私有属性或方法。

注:两个下划线 开始的变量是私有变量,不能通过对象名访问,只能在类的函数里使用 self 变量访问

访问私有变量:法1 ----- 可以使用定义getset方法这种方式来实现。

# get_私有变量名:获取私有变量

# set_私有变量名:修改私有变量

class Person:
    def __init__(self,name,age):
        self.name = name
        self.age = age
        self.__money = 2000  # 使用 __ 修饰的属性,是私有属性

    def __shopping(self, cost):
      
        print('还剩下%d元'%self.__money)

    def test(self):
        self.__shopping(200) # __shopping私有方法只能在对象内部使用
        
# 在外部访问私有属性或方法
print(p._Person__money)  # 使用对象名._类名__私有属性名 可以直接访问对象的私有属性
p._Person__shopping(100)  # 使用对象名._类名__函数名 可以直接调用对象的私有方法
2. property的使用

3. 实例属性、类属性

1.实例属性:对象的属性。每个对象单独保存的属性。

定义在 init 里面的属性是 实例属性

2.Person 类也是对象,我们称之为 类对象 。

定义在 init 外面的属性是 类属性;所有的实例对象都能访问。


注:1. 类属性不能通过实例对象来修改。只能通过类对象来修改。2. 尽量避免类属性和实例属性同名。如果有同名实例属性,实例对象会优先访问实例属性,如果没有实例属性,会新添加实例属性。

4. 类方法 和 静态方法
  • 如果一个方法没有用到实例对象和类对象,self参数可以省略。同时需要把这个方法标记为静态方法------@staticmethod。静态方法不需要使用带实例属性,可以通过实例对象和 类对象调用

  • 如果一个方法只用到了类属性,可以将这个方法设置为类方法------@classmethod

  • 调用 实例方法、类方法、静态方法
# 实例方法
# 类方法
# 静态方法
5. 继承:属性和方法
# 父类 基类:
class Person(object): # 默认最大的父类
    pass
# 子类:
class Student(父类):  # 继承父类的方法
    pass

继承方式

# 1. 支持多重继承:object---->>Person---->>Student
# 如果子类自己 有的方法,父类也有,会调用自己的,用来对父类进行重写,即方法重写
#如果子类自己  没有的方法就调用父类的

# 2. 多继承: __mro__ 方法查询调用的父类顺序
class Student(父类1,父类2):
	pass


6. 多态

7. new方法 与 单例设计模式
# 调用__new__ 方法申请内存地址 ,再调用 init 方法填入参数

# 单例设计模式:重写 new 方法,保证创建对象时,对象都是唯一的。即保证内存地址(对象)是唯一的

8. 其他魔法方法
# 内置属性和方法

十五 . 异常概念
1. 系统已定义异常
try:   # 如果输入内容不满足条件 不报错,直接走except
    b = float(input('请输入一个小数'))
    print(b*2)
    
# except 可以给出多个
except (IOError,NameError): 
    print('输入的不合法')
except Exception as e:
    print('输入的不合法')
except Exception as e:
    print('输入的不合法')
    
# Exception 指的错误类型:typeerror....
except TypeError as e:
    print('数据类型错误')
    
else:
	print('没有异常')
try...except...finally...
# 在程序中,如果一个段代码必须要执行,即无论异常是否产生都要执行,那么此时就需要使用finally。 比如文件关闭,释放锁,把数据库连接返还给连接池等。
# finally 不管发生什么都会执行finally后面的语句

2. 自定义异常
class LengthError(Exception):
	pass
	
s = input('请输入 --> ')
if len(s) < 3:
# raise 引发一个自定义的异常
	raise ShortInputException(len(s), 3)
3. with关键字
# 在进入with代码块时,会自动调用__enter__方法
# 在退出时,自动调用__exit__方法
# 没有处理异常的功能
4. 上下文管理器------with
with语句实质上是一个上下文管理器,with语句后的对象都会有__enter__()和__exit__()方法。
在进入到上下文时,会自动调用__enter__()方法;
程序正常执行完成,或者出现异常中断的时候,都会调用__exit__()方法。
十六 . 模块和包
1. 模块

一个模块就是一个包

import 模块名
from 模块名 import 功能名
from 模块名 import *
import 模块名 as 别名
from 模块名 import 功能名 as 别名
2. 自定义模块
# 当你导入一个模块,Python解析器按照搜索路径来查找 py 文件,也就是说我们的 py 文件必须在模块搜索路径的某一个文件夹里。也就是说有自己搜索的路径文件及文件夹

# 所以在习惯上,我们会把自己写的代码放到同一个项目文件夹。

dir(s)   # dir 显示出 s 所有的方法和属性
3. __all__

4. __name__

5. 包的使用

一个包即是 含有名字为–init–的 py 文件 的文件夹

十七.迭代器 和 生成器
1. 迭代器
# 判断 num 是否是可迭代对象(Iterable)
isinstance(num,Iterable)
# 判断 num 是否是Person类的实例对象
isinstance(num,Person)

# 使用iter、next 方法 需手动调用
b = iter(a) # 获取对象 a 的迭代器 b
next(a)     # 调用 迭代器 b 的 next方法
print(next(a))  # 获取返回的结果,一个print就是一个返回值,相当于for in循环一次
# 自定义 range类
class Range(object):
    def __init__(self, end, start, step=1):
        if start is not None:
            end, start = start, end    # 交换值
        if start is None:
            start = 0
        if step == 0:
            raise ValueError('Range() arg 3 must not be zero')
        self.end = end
        self.start = start
        self.step = step

    def __iter__(self):    # 重写__iter__方法
        return self

    def __next__(self):
        if self.start<self.end and self.step<0:
            raise StopIteration

        x = self.start
        self.start += self.step
        if self.start <= self.end:
            return x
        else:
            raise StopIteration

# for in 循环的本质是不断调用 next方法
r = Range(1, 5)
for i in r:
    print(i)
# 手动调用,几个print就是输出几个返回值
n = iter(m)
print(next(n))
print(next(n))
print(next(n))   # 3个print相当于for in循环了3次
2.生成器
# 生成器是一种特殊的迭代器,结构和函数结构一样
# 生成器的迭代器就是它自己 

def number_generator(n):
    print('hello')
    i = 0
    while i < n:
        print('呵呵呵')
        i += 1
        # return i
        yield i  # 使用关键字 yield    遇见就停止
        print('嘿嘿嘿')


# 调用 生成器函数的时候,并没有执行这个函数
G = number_generator(10)
print(G)  # 函数里使用 yield 关键字,得到的结果是一个生成器
print('-' * 30)
# 当调用 next 方法,获取下一个数据的时候,才会执行生成器里的代码
# 遇到 关键字  yield 就将 yield 的结果返回,程序停止
x1 = next(G)    # G是生成器 也是迭代器,可直接调用 next方法,省略了iteration的使用
print(f'x1的值是{x1}')

# 再一次调用 next 会在上次停留的位置继续执行
x2 = next(G)
print(f'x2的是{x2}')

x3 = next(G)


十八.网络编程

# 使用UDB发送消息
# 使用socket 实现网络连接
import socket
# 创建一个基于UDP连接的socket
send_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
send_socket.close()
# socket函数里面,family 用来指定scoket 的连接方式,通常使用AF_INET,用来建立一个基于网络连接的socket
# type 指定scoket连接的类型,可选 DGRAM ==> UDP    STREAM ==> TCP

with socket.socket(socket.AF_INET,socket.SOCK_DGRAM) as s:
    # sendto 发送数据,需要两个参数
    # data:发送的数据,需要是二进制
    # address:要发送到哪个地址,需要的是一个元组
    # 元组里又需要两个元素,第0个是IP地址,第1个是端口号
    s.sendto('good morning'.encode('utf8'),('10.11.54.110',8080))
    
    # recvfrom 接收消息
    # data = s.recvfrom(1024)  # 1024  指定接受的字节大小
    # print(data)  # 接收到的数据类型是一个元组
    data, (ip,port) = s.recvfrom(1024)  # 将接收到的数据拆包 
    print(f'接收到了来自{ip}:{port}的消息,内容是{data.decode("utf8")
# UDB聊天
import socket

ip = '10.11.54.110'
port = 8080

msg = input('请输入您要发送的数据:').encode('utf8')

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 如果想要主动的让别人发送消息 必须绑定端口号
s.bind(('10.11.54.88', 8888))
s.sendto(msg,(ip,port))
data ,(s_ip,s_port) = s.recvfrom(1024)
print(f'接收到了来自{s_ip}:{s_port}的消息,内容是:{data.decode("utf8")}')

十九.正则表达式
1.正则表达式

# 正则表达式 是一种特殊的字符序列,通常被用来检索、替换那些符合某个模式(规则)的文本。
# 正则表达式语法
re.match(pattern,string,flags=0)
# pattern:匹配的正则表达式
# string:要匹配的字符串
# flags:标志位,用于规定正则表达式的匹配方式,如:是否匹配大小写,多行匹配
re.search(r'\d', 'abe43e') 
# r'\d':匹配字符串'abe43e'中的 \d(数字),'abe43e':要匹配的字符串


# 在Python中需要通过正则表达式对字符串进行匹配的时候,可以使用re模块。 re 模块使 Python 语言拥有全部的正则表达式功能。
improt re

2.正则查找
# 查找方法  match\fullmatch\search\findall\finditer
# 得到的是 re.Match 类型的对像
improt re

# match 只从字符串开头开始匹配 ,只匹配开头,匹配不到返回 None
# re.match(r'H', 'Hello')  查找字符 H
print(re.match(r'H', 'Hello'))     # <re.Match object; span=(0, 1), match='H'>
print(re.match(r'e', 'Hello'))     # None

# fullmatch 使用正则规则从头开始对整个字符串全部进行匹配
print(re.fullmatch(r'ab\d+', 'ab128cd'))  # None 不全是\d,还有字母
print(re.fullmatch(r'ab\d+', 'ab2342130')) # <re.Match object; span=(0, 9), match='ab2342130'>

# search 扫描整个字符串,并返回第一个成功匹配的字符,只匹配一次;找不到就返回 None
# + 表示 该字符有一个或者多个
print(re.search(r'\d', 'abe43e'))  # 只匹配一次 数字(\d:表示数字)
print(re.search(r'\d+', 'abe43e')) # 一次或者多次匹配 数字

# finditer 会将字符串里所有匹配到的结果都查询到,得到的结果是一个迭代器 x
# 迭代器 x 里每个元素 又是 一个 re.Match 类型的对象!!!

x = re.finditer(r'3\d+', 'ab128cd347820ef3214ab34x')
for i in x:
    print(i)
"""
结果:
<re.Match object; span=(7, 13), match='347820'>
<re.Match object; span=(15, 19), match='3214'>
<re.Match object; span=(21, 23), match='34'>
"""

# findall 得到的结果是一个列表
# 这个列表里保存的是匹配到的结果字符串!!!
word = 'ab128cd347820ef3214ab34x'
y = re.findall(r'3\d+', word)
print(y)  #  ['347820', '3214', '34']

3. re.Match类型
x = re.search(r'\d+', 'ab98cd34uxm') # x 是一个re.Match 类型的对象

# 用dir(x)获取对象的属性和方法
print(x1.end())  # 获取匹配到的字符串的结束下标
print(x1.endpos)  # 整个字符串的长度(最大下标+1)

print(x1.span())  # 得到的结果是一个元组,表示匹配到的字符串的开始(包含)和结束(不包含)下标

print(x1.string)  # 查找的完整的字符串

# 使用 group 来获取匹配到的结果字符串!!!
print(x1.group())  # 98  得到的结果是匹配到的字符串!!!
# x1.group() 拿到所有子分组匹配到的字符串组成的一个元组


4.正则表达式里的group
# 正则表达式使用 () 用来进行分组
# (?P<test>b\d+)  (c\d+) ,加()是将匹配到的结果分组
# (?P<test>b\d+) 将匹配的 b\d+ 起一个组名
x2 = re.search(r'(b\d+)(c\d+)(?P<zuming>d\d+)e\d+', 'a10b2453c5896d717e123')  # 分为 4 个分组
print(x2)  # <re.Match object; span=(3, 21), match='b2453c5896d717e123'>

# 'group', 'groups', 'lastgroup', 'groupdict'

# 如果是 0  个分组, 0 可以省略  group(0) <==> group()

print(x2.group(0))  # b2453c5896d717
print(x2.group(1))  # b2453
print(x2.group(2))  # c5896
print(x2.group(3))  # d717

# 最后匹配的一个分组的组名
print(x2.lastgroup)  # zuming

# groupdict 是以字典的形式保存有组名的分组数据
print(x2.groupdict())              # {'zuming':'d717'}
print(x2.groupdict()['zuming'])    # d717

5. re.compile 的介绍
import re
# 1.和2.的结果一样
# 1.
print(re.search(r'm\d+', 'ab322wm234dasdd'))
# <re.Match object; span=(6, 10), match='m234'>

#2. 
pattern = re.compile(r'm\d+')
print(pattern.search('ab322wm234dasdd'))  # <re.Match object; span=(6, 10), match='m234'>


6.正则修饰符
# 正则表达式语法
re.match(pattern,string,flags=0)
# flags 是正则修饰符,对正则规则有不同的含义

# re.I  ==> 让正则修饰符忽略大小写
print(re.search(r'd', 'gooDokXhi'))         # None
print(re.search(r'd', 'goodDokXhi', re.I))  # <re.Match object; span=(3, 4), match='D'>

# re.S  ==> 让 '.' 匹配包括换行的任意字符
print(re.findall(r'.', 'a\n1_*/({+'))        # 无换行 ['a', '1', '_', '*', '/', '(', '{', '+'] 
print(re.findall(r'.', 'a\n1_*/({+', re.S))  # 有换行 ['a', '\n', '1', '_', '*', '/', '(', '{', '+'] 
7.正则匹配规则
# 正则匹配规则
# 1. 数字和字母表示它本身,

# 2. \ 有特殊含义 ,用来做转义

# 3. 大多数字母前面加 \ 转义后,会有特殊含义(重点)
\n 换行  \r回车   \t制表符   
\s 匹配空白字符(空格回车tab键,看不到的)   \S非空白字符
\d 数字       \D非数字
\w 数字字母和下划线 _   \W非数字字母下划线

# 4. 绝大多数标点符号都有特殊含义(重点|难点)
'.': 匹配 除了 \n 以外的任意字符
'+': 所匹配字符 的出现次数至少为1,一次或多次
    
# 5. 如果想要表示标点符号本身,需要使用 \ 转义字符
'\.':表示 . 本身
8.符号和标点的特殊含义
import re

# ?:表示字符最多出现一次;让贪婪模式转换成为非贪婪模式  <==> {,1}
print(re.search(r'go?d', 'goood'))  # 匹配o最多出现一次,这个结果是 None


# {}: 用来限定字符出现的次数
# {n}:表示字符出现n次
# {,n}:表示字符最多出现n次(包含n次)
# {m,n}:表示字符串出现m(包含)到n(包含)次
# {n,}:表示字符至少出现n次
print(re.search(r'a\d{3}x', 'a519x'))
print(re.search(r'a\d{,3}x', 'ax'))
print(re.search(r'a\d{3,5}x', 'a25367x'))
print(re.search(r'a\d{3,}x', 'a1546x'))
"""
结果:
# <re.Match object; span=(0, 5), match='a519x'>
# <re.Match object; span=(0, 2), match='ax'>
# <re.Match object; span=(0, 7), match='a25367x'>
# <re.Match object; span=(0, 6), match='a1546x'>
"""

# () 用来分组
print(re.search(r'b\d+(c\d+)d\d+', 'a34b12c45d78').group(1))
# 得到的第一个分组是 'c45'



# [] 用来表示区间范围  \d ==>[0-9]  \w ==> [0-9a-zA-Z_]
print(re.search(r'x[1-5]+p', 'dskx347pix12312p'))
print(re.search(r's[a-d]+j', 'ewisxyajioesabcj'))
print(re.search(r'p[a-d0-3]+x', 'dpac21x'))
"""
结果:
<re.Match object; span=(9, 16), match='x12312p'>
<re.Match object; span=(11, 16), match='sabcj'>
<re.Match object; span=(1, 7), match='pac21x'>
"""

print(re.findall(r'u[352a]x', 'u3xiu5xpu2xouax'))
# 结果:['u3x', 'u5x', 'u2x', 'uax']
# | 用来表示可选值,和 [] 有区别,通常配合 () 使用
x = re.finditer(r'u(3|5|2|a)x', 'u3xiu5xpu2xouax')  # 单个字符时,更加推荐使用 [352a]
for i in x:
    print(i.group())
"""
结果:
u3x
u5x
u2x
uax
"""


print(re.findall(r'u[23674]x', 'u23xiu67xlu34x'))  # 结果为:None

y = re.finditer(r'u(23|67|34)x', 'u23xiu67xlu34x')
for i in y:
    print(i.group())
"""
结果:
u23x
u67x
u34x
"""


# ^ 表示以指定的字符开始; 放在 [] 里,表示取反

print(re.search(r'^st', 'amstp'))  # 等价于  re.match(r'st','amstp') 
print(re.findall(r'a[^1-5]+x', 'a123xdklsa789xauidsx')) # 匹配1-5之外的数字
# 结果:['a789xauidsx']
# $ 表示以指定的字符结束
print(re.search(r'mp$', 'xdkadskjsmp'))
# 同时使用 ^ 和  $ 等价于 fullmatch
print(re.search(r'^a\d+m$', 'ua94mt'))
print(re.search(r'a\d+m', 'ua94mt'))
print(re.fullmatch(r'a\d+m', 'ua94mt'))
9. 正则替换
# re.sub(pattern,repl,string,count=0)
"""
参数:
pattern : 正则中的模式字符串。
repl : 替换的字符串,也可为一个函数。
string : 要被查找替换的原始字符串。
count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。
"""
import re

a = 'a45b7d23x95'

# 将字符串中的数字替换为 T
print(re.sub(r'\d+', 'T', a))    # aTbTdTxT

# 利用lambda函数 将数字扩大2倍
print(re.sub(r'\d+', lambda x: str(int(x.group()) * 2), a))
# 结果:a90b14d46x190

# 定义函数 将数字扩大2倍
def test(x):
    data = x.group()
    return str(int(data) * 2)
# 结果:a90b14d46x190
10.贪婪模式和非贪婪模式
贪婪模式:匹配尽可能多的字符
非贪婪则相反,总是尝试匹配尽可能少的字符
在*,?,+,{m,n}后面  加上 ? 使贪婪变成非贪婪。

<re.Match object; span=(0, 5), match=‘a519x’>

<re.Match object; span=(0, 2), match=‘ax’>

<re.Match object; span=(0, 7), match=‘a25367x’>

<re.Match object; span=(0, 6), match=‘a1546x’>

“”"


```python

# () 用来分组
print(re.search(r'b\d+(c\d+)d\d+', 'a34b12c45d78').group(1))
# 得到的第一个分组是 'c45'



# [] 用来表示区间范围  \d ==>[0-9]  \w ==> [0-9a-zA-Z_]
print(re.search(r'x[1-5]+p', 'dskx347pix12312p'))
print(re.search(r's[a-d]+j', 'ewisxyajioesabcj'))
print(re.search(r'p[a-d0-3]+x', 'dpac21x'))
"""
结果:
<re.Match object; span=(9, 16), match='x12312p'>
<re.Match object; span=(11, 16), match='sabcj'>
<re.Match object; span=(1, 7), match='pac21x'>
"""

print(re.findall(r'u[352a]x', 'u3xiu5xpu2xouax'))
# 结果:['u3x', 'u5x', 'u2x', 'uax']
# | 用来表示可选值,和 [] 有区别,通常配合 () 使用
x = re.finditer(r'u(3|5|2|a)x', 'u3xiu5xpu2xouax')  # 单个字符时,更加推荐使用 [352a]
for i in x:
    print(i.group())
"""
结果:
u3x
u5x
u2x
uax
"""


print(re.findall(r'u[23674]x', 'u23xiu67xlu34x'))  # 结果为:None

y = re.finditer(r'u(23|67|34)x', 'u23xiu67xlu34x')
for i in y:
    print(i.group())
"""
结果:
u23x
u67x
u34x
"""


# ^ 表示以指定的字符开始; 放在 [] 里,表示取反

print(re.search(r'^st', 'amstp'))  # 等价于  re.match(r'st','amstp') 
print(re.findall(r'a[^1-5]+x', 'a123xdklsa789xauidsx')) # 匹配1-5之外的数字
# 结果:['a789xauidsx']
# $ 表示以指定的字符结束
print(re.search(r'mp$', 'xdkadskjsmp'))
# 同时使用 ^ 和  $ 等价于 fullmatch
print(re.search(r'^a\d+m$', 'ua94mt'))
print(re.search(r'a\d+m', 'ua94mt'))
print(re.fullmatch(r'a\d+m', 'ua94mt'))
9. 正则替换
# re.sub(pattern,repl,string,count=0)
"""
参数:
pattern : 正则中的模式字符串。
repl : 替换的字符串,也可为一个函数。
string : 要被查找替换的原始字符串。
count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。
"""
import re

a = 'a45b7d23x95'

# 将字符串中的数字替换为 T
print(re.sub(r'\d+', 'T', a))    # aTbTdTxT

# 利用lambda函数 将数字扩大2倍
print(re.sub(r'\d+', lambda x: str(int(x.group()) * 2), a))
# 结果:a90b14d46x190

# 定义函数 将数字扩大2倍
def test(x):
    data = x.group()
    return str(int(data) * 2)
# 结果:a90b14d46x190
10.贪婪模式和非贪婪模式
贪婪模式:匹配尽可能多的字符
非贪婪则相反,总是尝试匹配尽可能少的字符
在*,?,+,{m,n}后面  加上 ? 使贪婪变成非贪婪。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值