PYTHON 基础
1. python 流程格式
1.1 变量赋值、运算与字符串表示、处理、判断
1 | name1 = name2 = name3 = '文件系统' |
变量运算表
| 运算 | 描述 |
| :——-: | :—————————————: |
| + - / | 加减乘除 (+可用于连接string) |
| % | 取模(102%100=2) |
| * | 幂次方(23=8) |
| // | 取除数(20//3=6) |
字符串输出表
方式 | 意思 |
---|---|
:, | 每 3 个 0 就用逗号隔开,比如 1,000 |
:b | 该数字的二进制 |
:d | 整数型 |
:f | 小数模式 |
:% | 百分比模式 |
1 字符串表示 ( %百分号模式 与 format功能 与 f格式化字符串)
1 | name = "hm" |
2 字符串处理与判断
string.strip() 去除两端的空白符
string.replace(“原始”,”新的”) 替换字符
string.lower() 全部做小写处理
string.upper() 全部做大写处理
string.title() 仅开头的字母大写
string.split(“|”) 按要求分割以|进行分割
“,”.join([]) 按要求合并中间添加,号
string.startswith(“你”) 判断是否为你字段开头
string.endswith(“哈哈”) 判断是否为哈哈字段结尾
1.2 条件判断、循环、跳出跳过(if/for/while/break/continue)
1 | ## IF |
1 | # python 从0开始 区间取值均为前闭后开:[3,10) 基础 |
1.3 数据类型
1.3.1 List列表、Dict字典、Tuple元组、Set集合
list “[]”—— 具有顺序、可存放不同类型;但是
1 | files = [1, "file", ["2", 3.2],"ha"] |
Dict “{“key”:value}”—— 注意字典中的元素是没有顺序的; key-value型
1 | files = {"ID": 111, "passport": "my passport", "books": [1,2,3]} |
Tuple “()”—— 存放数据值不能被改变,常用来存放有些常数或固定值。特别是代码交由别人使用时,你没法控制,也不希望他们改变你的这些固定值。
1 | files = ("file1", "file2", "file3") |
Set “set([])”或”{}”—— Set常用于去重,set里面只会存在非重复的元素,不管你往里面加了多少相同元素,这些相同元素都会坍缩成一个。 这种特性,我们就可以运用它来做交集并集等操作。注意集合中的元素也没有顺序的。
1 | my_files = set(["file1", "file2", "file3"]) |
list 内元素的增加与删除
1 | files = [] |
1.3.2 arrly数组 —— Numpy库
1.3.3 arrly表 —— Panda库
1.4 一些函数的妙用
1.4.1enumerate 自动加 index
使用enumerate函数替换 手动计数器 count 的存在.
1 | count = 0 |
1.4.2 Zip 同时迭代
同时处理多个列表,并把它们做成一个字典。
1 | name = ["a", "b", "c"] |
1.4.3 reverse & reversed 翻转列表
同时处理多个列表,并把它们做成一个字典。
1 | #自己就地反转 |
1.4.4 Deep Copy & Shallow Copy 复制要点
Deep copy 就是我们通常意义上的复制,把东西全部再造了一遍,彻底成为了两个独立的个体。
Shallow Copy, 其实也有一点地址拷贝的意思,通过地址进行映射。 所以真实的实体是没有被复制的,我只复制了这个实体的一个映射地址而已。
注:Python 他在创造之初,就有这么个约定,列表中直接存放的数值、字符,与存放class 实例,列表,字典不同。 对数值、字符的复制,直接是复制的值,而不是一个映射地址。
程序数据的无端更改其实很有可能就是浅复制造成的,改变了不该被改变的值。但是浅复制的优势就是快。复制是需要内存和时间的,因为浅复制没有真正复制。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#存放的数值、字符时相当于Deep Copy
l = [1,2,3]
_l = l.copy()
_l[0] = -1
print(_l)
print(l)
#> [-1, 2, 3]
#> [1, 2, 3]
#存放的列表时 .copy只是浅拷贝Shallow Copy
l = [[1],[2],3]
_l = l.copy()
_l[0][0] = -1
print(_l)
print(l)
#> [[-1], [2], 3]
#> [[-1], [2], 3]
#存放的列表时 如何深拷贝哪?
from copy import deepcopy
l = [[1],[2],3]
_l = deepcopy(l)
_l[0][0] = -1
print(_l)
print(l)
#> [[-1], [2], 3]
#> [[1], [2], 3]
1 | #存放的数值、字符时相当于Deep Copy |
2. python 框架格式
2.1 函数(Function) — 类 (Class) — 模块 (Module)
✅函数功能 :目的用于基础功能复用,简化程序流程
1 | g=3 |
✅类 :在程序中描述具体的一个物体。 比如一只猫有哪些特征,它能做哪些动作。 工程师想出了一个在代码中设置猫特征和动作的办法, 这就有了 class 类的概念。
类的目的
: 基于梳理逻辑步骤形成类,用于统筹管理函数,为函数分类使之条理清晰。 e.g. 数据处理类
(用于实现读写文件、数据提取、正则化、json序列化传输等函数功能)、求解问题类
(问题参数、编解码目标函数计算、初始化种群、甘特图绘制等函数)、算法模块
(naga-ii\moea/d\RL等类,每个类里包含诸如选择交叉变异的函数)、工具类
(获取前沿面、轮盘赌等函数)
a) 类的封装: 封装自己的属性和功能,把一个对象的属性私有化,同时提供一些可以被外界访问的属性的方法,如果存在不想被外界使用的方法,我们可私有化不提供方法给外界访问。
1 | # 用 class File 来创建一个大概念(类),注意我们通常约定类的名字要首字母大写。 |
| 私有形式 | 特点 |
| :———————-: | :————————————————————————————: |
| _ 一个下划线开头 |
弱隐藏
不想让别人用 (别人在必要情况下还是可以用的) || __ 两个下划线开头 |
强隐藏
不让别人用 |
b) 类的继承与多态:
继承:是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类。集成特点如下:
- 父类变,子类就必须变
- 继承破坏了封装,对于父类而言,它的实现细节对与子类来说都是透明的。
- 继承是一种强耦合关系
多态:若子类重写了父类中的某些方法,在调用该些方法的时候,必定是使用子类中定义的这些方法(动态连接、动态调用)。实现多态有三个必要条件:继承、重写、调用父类的属性/函数。
1 | class Fjsp_RMT_singe(Fjsp_RMT): # 继承了 Fjsp_RMT 的属性和功能 |
✅模块 :module主要是为了一个相对比较大的工程,涉及到多个文件之间的互相调用关系。
算法模块
(包括naga-ii\moea/d\RL等类,每个类里包含诸如参数等属性以及选择、交叉、变异的函数功能)。
⭕统一规范:不涉及python包时均使用 import as A 形式;涉及到 python包时采用from A import 形式并与init.py配合(原因:一般通用类都用 import numpy as np的形式,而python包中基本都是自己创建的程序类有实际用途所以包是空壳子没必要带着)
1 | #**如下代码显示了模块调用、导入的两种形式** |
上述两者的区别是:
- 如果用 import FJSP_RMT as problem,我们在调用FJSP_RMT.py中定义的函数fun1()或类class1()时,需要写成 problem.fun1()或problem.class1();
- 如果用 from FJSP_RMT import *,我们在调用FJSP_RMT.py中定义的函数fun1()或类class1()时,可以直接写成 fun1()或class1();
1
2
3
4
5
6
7
8
9# Algorithm模块下的NSGA2.py 和 main.py 在不同级的目录下 (main调用Algorithm时)
from Algorithm import *
# 在Algorithm模块下的__init__.py中输入该行代码 .NSGA2代表返回上一目录后找到NSGA2.py
from .NSGA2 import NSGA2
则我们在调用NSGA2.py中定义的函数fun1()或类class1()时,可以直接写成 fun1()或class1();
import Algorithm.NSGA2 as NSGA2
并把Algorithm模块下的__init__.py清空
则我们在调用NSGA2.py中定义的函数fun1()或类class1()时,可以直接写成 NSGA2.fun1()或NSGA2.class1()2.2 异常处理(try-except\raise) 与 单元测试 (Unittest)
✅异常处理(try-except)
代码出错不可避免,即便自己编写代码做到无错误 ,如果你的代码基于他人的代码,别人代码出错。即使别人的代码不出错,但是也有可能物理环境会出错呀,比如 CPU 超了,某人的服务运行失败,你恰好又是基于他提供的服务,你也跟着超时了。这些都会让你的程序报错。异常处理就是帮助我们去处理错误,预估到可能会报什么错误然后用try-except 结构包住处理,达到不妨碍接下来的代码执行。1
2
3
4
5
6
7
8#try-except 结构 同时处理多个异常
d = {"name": "f1", "age": 2}
l = [1,2,3]
try:
v = d["gender"]
l[3] = 4
except (KeyError, IndexError) as e:
print("key or index error for:", e)还有一个 try-except-else 的模式,在 else 中处理没有报错的情况。报错情况下不会执行else下的代码,不报错会执行。1
2
3
4
5
6
7
8
9
10
11
12
13
14#try-except 结构 分开处理多个异常
d = {"name": "f1", "age": 2}
l = [1,2,3]
try:
v = d["gender"]
l[3] = 4
except KeyError as e:
print("key error for:", e)
d["gender"] = "x"
except IndexError as e:
print("index error for:", e)
l.append(4)
print(d)
print(l)如果 else 是为了执行没有异常的状况,那么 finally 就是为了执行 不管有没有异常 的情况。无论有报错还是没报错,finally 下面的代码都会运行。1
2
3
4
5
6
7
8
9# try-except-else 结构
l = [1,2,3]
try:
l[3] = 4
except IndexError as e:
print(e)
else:
print("no error, now in else")上面这两种模式主要用在什么 case 当中呢?你想一下,是不是有些时候,不管你有没有报错,你都想让程序去执行什么。我们甚至都不需要为任何异常做任何处理。 这种时候也就是说,你有异常,我不让你终止主程序,你没有异常吧,万事大吉。1
2
3
4
5
6
7
8
9# try-except-finally 结构
l = [1,2,3,4]
try:
l[3] = 4
except IndexError as e:
print(e)
finally:
print("reach finally")✅raise手动触发异常1
2
3
4try:
dddd = dddddd
finally:
print("I know there is error, so what?")
raise 是你为别人犯错留下的证据,或者是告诉别人你怎么犯错的。这个信息对于别人 dubug 你的代码十分有好处。另一种情况是,你写了成百上千行代码,你也不能全记住代码的每一个细节。所以一旦报错,你也需要一个友善的错误信息提示,这时用 raise 准没错。1
2
3
4
5
6
7def no_negative(num):
if num < 0:
raise ValueError("I said no negative")
return num
print(no_negative(-1))
# Traceback (most recent call last):
# ValueError: I said no negative
异常名称 | 描述 |
---|---|
BaseException | 所有异常的基类 |
SystemExit | 解释器请求退出 |
KeyboardInterrupt | 用户中断执行(通常是输入^C) |
Exception | 常规错误的基类 |
StopIteration | 迭代器没有更多的值 |
GeneratorExit | 生成器(generator)发生异常来通知退出 |
StandardError | 所有的内建标准异常的基类 |
ArithmeticError | 所有数值计算错误的基类 |
FloatingPointError | 浮点计算错误 |
OverflowError | 数值运算超出最大限制 |
ZeroDivisionError | 除(或取模)零 (所有数据类型) |
AssertionError | 断言语句失败 |
AttributeError | 对象没有这个属性 |
EOFError | 没有内建输入,到达EOF 标记 |
EnvironmentError | 操作系统错误的基类 |
IOError | 输入/输出操作失败 |
OSError | 操作系统错误 |
WindowsError | 系统调用失败 |
ImportError | 导入模块/对象失败 |
LookupError | 无效数据查询的基类 |
IndexError | 序列中没有此索引(index) |
KeyError | 映射中没有这个键 |
MemoryError | 内存溢出错误(对于Python 解释器不是致命的) |
NameError | 未声明/初始化对象 (没有属性) |
UnboundLocalError | 访问未初始化的本地变量 |
ReferenceError | 弱引用(Weak reference)试图访问已经垃圾回收了的对象 |
RuntimeError | 一般的运行时错误 |
NotImplementedError | 尚未实现的方法 |
SyntaxError | Python 语法错误 |
IndentationError | 缩进错误 |
TabError | Tab 和空格混用 |
SystemError | 一般的解释器系统错误 |
TypeError | 对类型无效的操作 |
ValueError | 传入无效的参数 |
UnicodeError | Unicode 相关的错误 |
UnicodeDecodeError | Unicode 解码时的错误 |
UnicodeEncodeError | Unicode 编码时错误 |
UnicodeTranslateError | Unicode 转换时错误 |
Warning | 警告的基类 |
DeprecationWarning | 关于被弃用的特征的警告 |
FutureWarning | 关于构造将来语义会有改变的警告 |
OverflowWarning | 旧的关于自动提升为长整型(long)的警告 |
PendingDeprecationWarning | 关于特性将会被废弃的警告 |
RuntimeWarning | 可疑的运行时行为(runtime behavior)的警告 |
SyntaxWarning | 可疑的语法的警告 |
UserWarning | 用户代码生成的警告 |
✅单元测试 (Unittest)
代码调试是编写代码的至关重要的一环。尤其是你要写一些功能服务给别人用的时候,免不了要先自测有没有问题。保证我写的,真的是我想要的。
使用场景: 程序的代码量小,且项目功能之间无耦合关系时,可运行程序打断点进行debug。但是当处理的代码量比较大,牵扯到的资源相对多,我很多时候并不知道哪里会不会有错误。 所以这种情况非常依赖于测试。让自动化测试帮我处理任何改动可能带来的问题。
unittest 规范:首先 unittest 不会被其他人使用到,纯粹是你自己为了验证自己写的代码有没有问题的方式。一般般采用 XXXX.py与XXXX_test.py的形成进行单元测试。另外,你可以按照 unittest 当中的 case 为蓝本,去完善你原函数的功能。 就好像有了一个目标,你要为了这个目标去开发功能一样。这样就可以先写 unittest 当中的 case,比如下面,我不会先写 my_func 里面的内容,而是先把我的测试和要验收的指标写好。然后后面我再开发功能。
1 | # main.py 主文件用于编写程序 |
assert | 含义 |
---|---|
assertEqual(a, b) | a == b |
assertNotEqual(a, b) | a != b |
assertTrue(condition) | condition 是不是 True |
assertFalse(condition) | condition 是不是 False |
assertGreater(a, b) | a > b |
assertGreaterThan(a, b) | a >= b |
assertLess(a, b) | a < b |
assertLessEqual(a, b) | a <= b |
assertIs(a, b) | a is b,a 和 b 是不是同一对象 |
assertIsNot(a, b) | a is not b,a 和 b 是不是不同对象 |
assertIsNone(a) | a is None,a 是不是 None |
assertIsNotNone(a) | a is not None,a 不是 None? |
assertIn(a, b) | a in b, a 在 b 里面? |
assertNotIn(a, b) | a not in b,a 不在 b 里? |
assertRaises(err) | 通常和 with 一起用,判断 with 里的功能是否会报错 |
2.3 生成器与装饰器
生成器 Generator,一种占用更小内存的方式处理循环迭代,可以说生成器就是为循环设计的。生成器是一种优化代码程序节省占用内存的方法,如果当你的循环内存不足时,或者运行很慢时,生成器是你需要考虑的。
在循环的时候,我们的目的是为了每次循环拿到一些特定数据,然后为这些数据做处理。但是无可避免的会在内存中记录这些数值, 当需要记录的数值很多的时候,我们的内存可能就吃不消了。而生成器就是用来现用现存的
,我们只在需要这个数据的时候生成它,生成完了我就不用了,也不需要记录。这种时候将会节约我很多内存的需求。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 def need_return():
for item in range(5):
if item % 2 == 0:
print("我要扔出去一个 item=%d 了" % item)
yield item # 这里就会返回给下面的 for 循环
print("我又回到里面了")
for i in need_return():
print("我在外面接到了一个 item=%d\n" % i)
>>
#我要扔出去一个 item=0 了
#我在外面接到了一个 item=0
#
#我又回到里面了
#我要扔出去一个 item=2 了
#我在外面接到了一个 item=2
#
#我又回到里面了
#我要扔出去一个 item=4 了
#我在外面接到了一个 item=4
#
#我又回到里面了
定义生成器类
用一个 class 也是可以表示一个迭代器,生成器的。 如果我们将上面的逻辑转化成class
,这个 class 可能相对比较复杂,但是也意味着你可以有更多设置和控制发生在这个 class 里面。 里面我们申明了用于生成器的两个 method,__iter__ 和 __next__。
__iter__ 的意思是,当我在外面 for 循环进行迭代时,我返回什么?在下面例子中,我就把自己这个 class 本身返回回去,继续让自己做迭代就好了。
__next__ 的意思是每次迭代的时候,我的函数会放出来什么元素。下面的功能中实现的就是放出来一个被计算过的 item 元素。
1 | class NeedReturn: |
装饰器 Decorator 它是一个装饰 Python Function 的东西。 Function 为什么要被装饰?那就是我们想为这个 Function 做些额外的事情。但是只为一个 Function 做这件事,那我们还不如直接改掉这个 Function,让它直接干这件事就好了。 Decorator 的好处就是,我们可以给批量的 Function 都做这件事。当有一批 Function 都要做些前置或者后置的工作,我们可以统一给他们装修,用一个装饰器统一处理从而减轻你的开发量,特别是针对于不同 function,要做同样的前置处理或后置处理的时候。
比如数据库的处理,来了一条数据,我先要验证这个数据的准确性,然后进行个性化 function 的处理,最后将加工后的数据写入数据库。
网页个人页的鉴权,用户每一个点击,我都先需要鉴权,才能做后续不同的 function。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 def authorization(fn): #authorization 与@authorization一致即可
def check_and_do(name):
if name != "hm": # 鉴权
print(name + " has no right!")
return
res = fn(name)
return res
return check_and_do #返回值check_and_do与函数功能check_and_do一致即可
#装饰器格式
def outer1(name):
print(name+" outer1")
def outer2(name):
print(name+" outer2")
def outer3(name):
print(name+" outer3")
outer1("hm")
outer2("hmm")
outer3("hm")
>>
#hm outer1
#hmm has no right!
#hm outer3
2.4 工程问题编程思路
问题聚焦: 我们面临一个什么具体问题需要进行解决,最终简化问题提取关键核心点(实际存在并且是有研究或者工程应用价值)
产品定位: 为解决此问题我们需要做什么,实现什么功能来创造价值。
程序设计: 梳理需要实现的各个模块功能间的逻辑关系,形成模块-类-功能的编程架构;定制解决方案系统设计功能的开发,尽可能的成系统编程、可复用代码从而优化编程架构。
程序开发: 基于形成的模块-类-功能的编程架构进行具体开发,并根据开发过程中遇到的问题不断完善流程和克服问题。
3. python 文件数据处理
3.1文件数据读写
3.1.1 基础读写
1 | # with结构(将文件的打开和关闭嵌入到了一个 with 架构中不用担心忘记关闭文件) |
1 | # 编码格式与中文乱码 |
MODE | 含义 |
---|---|
w | (创建)写文本 |
r | 读文本,文件不存在会报错 |
a | 在文本最后添加 |
wb | 写二进制 binary |
rb | 读二进制 binary |
ab | 添加二进制 |
w+ | 又可以读又可以(创建)写 |
r+ | 又可以读又可以写, 文件不存在会报错 |
a+ | 可读写,在文本最后添加 |
x | 创建 |
3.1.2 Numpy库中的数据读写
3.1.3 Panda库中的数据读写
3.2文件目录管理(OS库)
1 | import os |
(感性认识)Dictionary和package的使用,存储资源等不需要执行诸多种类的程序时采用Dictionary 否则用package
Dictionary在pycharm中是一个文件夹目录,放置资源文件,对应于在进行JavaWeb开发时用于放置css/js文件的目录,或者说在进行物体识别时,用来存储背景图像的文件夹。该文件夹其中并不包含_ _ init.py_ _文件。
Python package 包文件夹而言,与Dictionary不同之处在于其会自动创建_ _ init.py_ _ 文件。其包括一组模块和一个 _ _ init.py_ _ 文件。该包的使用与Python的import机制有关,这关乎到你的哪些.py文件是对外可访问的。有些时候,如果一个包下有很多模块,在调用方import如此多模块是很费事,且不优雅的,此时可以通过修改 _ _ init_ _.py来完成该任务。
3.3正则表达式匹配(未完成)
在文件、文字查找、匹配、替换、处理时,少不了要根据特定规则来处理对应文字的情况。 正则表达式 Regular Expression(regex —— re库)就是通过用一些规则或者模板来帮你找到文字,替换文字的工具。
正则库功能表
| 功能 | 说明 | 举例 |
| :—————-: | :———————————————————————————————————————————: | :—————————————————————————————————————————————: |
| re.search() | 扫描查找整个字符串,找到第一个模式匹配的 | re.search(r”run”, I run to you) > ‘run’ |
| re.match() | 从字符的最开头匹配,找到第一个模式匹配的即使用 re.M 多行匹配,也是从最最开头开始匹配 | re.match(r”run”, I run to you) > None |
| re.findall() | 返回一个不重复的 pattern 的匹配列表 | re.findall(rr[ua]n, I run to you. you ran to him) > [‘run’, ‘ran’] |
| re.finditer() | 和 findall 一样,只是用迭代器的方式使用 | for item in re.finditer(rr[ua]n, I run to you. you ran to him): |
| re.split() | 用正则分开字符串 | re.split(rr[ua]n, I run to you. you ran to him) > [‘I ‘, ‘ to you. you ‘, ‘ to him’] |
| re.sub() | 用正则替换字符 | re.sub(rr[ua]n, jump, I run to you. you ran to him) > ‘I jump to you. you jump to him’ |
| re.subn() | 和 sub 一样,额外返回一个替代次数 | re.subn(rr[ua]n, jump, I run to you. you ran to him) > (‘I jump to you. you jump to him’, 2) |
通用匹配方式表
| 特定匹配标识 | 表达含义 | 实际范围 |
| :—————: | :———————————————————: | :———————————————————————————-: |
| \d | 任何数字 | [0-9] |
| \D | 不是数字的 | |
| \s | 任何空白字符 | [ \t\n\r\f\v] |
| \S | 空白字符以外的 | |
| \w | 任何大小写字母,数字和 _ | [a-zA-Z0-9_] |
| \W | \w 以外的 | |
| \b | 匹配一个单词边界 | 比如 er\b 可以匹配 never 中的 er,但不能匹配 verb 中的 er |
| \B | 匹配非单词边界 | 比如 er\B 能匹配 verb 中的 er,但不能匹配 never 中的 er |
| \\ | 强制匹配 \ | |
| . | 匹配任何字符 (除了 \n) | |
| ? | 前面的模式可有可无 | |
| * | 重复零次或多次 | |
| + | 重复一次或多次 | |
| {n,m} | 重复 n 至 m 次 | |
| {n} | 重复 n 次 | |
| +? | 非贪婪,最小方式匹配 + | |
| ? | 非贪婪,最小方式匹配 | |
| ?? | 非贪婪,最小方式匹配 ? | |
| ^ | 匹配一行开头,在 re.M 下,每行开头都匹配 | |
| $ | 匹配一行结尾,在 re.M 下,每行结尾都匹配 | |
| \A | 匹配最开始,在 re.M 下,也从文本最开始 | |
| \B | 匹配最结尾,在 re.M 下,也从文本最结尾 | |
1 | # (举例说明)注册管理,验证邮箱是否有效。 |
1 | #同时满足多种条件的pattern写法 |
1 | #中文识别 |
在模式中获取特定信息
我们能用 group
和()
获取到特定位置的信息。只要我们在正则表达中,加入一个 ()
选定要截取返回的位置, 他就直接返回括号里的内容。
1 | ## re.finditer提供了 file.group(0) 这种全匹配的信息,而re.findall未提供全匹配信息。 |
名字索引
有时候
group
的信息太多了,括号写得太多,依靠数字位置索引识别信息容易错配?此时,我们还能用一个名字来索引匹配好的字段, 然后用 group(“索引”) 的方式获取到对应的片段。注意,re.findall
不提供名字索引的方法, re.search
或者 re.finditer
可以用名字索引。为了索引,我们需要在括号中写上 ?P<索引名>
这种模式。1 | match = re.finditer(r"(?P<y>\d+?)-(?P<m>\d+?)-(?P<d>\d+?)\.jpg", string) |
多模式匹配
在正则中还有一些特别的
flags
,可以在 re.search
,re.match()
,re.findall()
等功能中使用。 主要目的也是方便我们编写正则,和用更简单的方法处理更复杂的表达式。| 模式 | 全称 | 说明 |
| :—-: | :————————: | :———————————————————————————————: |
| re.I | re.IGNORECASE | 忽略大小写 |
| re.M | re.MULTILINE | 多行模式,改变’^’和’$’的行为 |
| re.S | re.DOTALL | 点任意匹配模式,改变’.’的行为, 使”.“可以匹配任意字符 |
| re.L | re.LOCALE | 使预定字符类 \w \W \b \B \s \S 取决于当前区域设定 |
| re.U | re.UNICODE | 使预定字符类 \w \W \b \B \s \S \d \D 取决于unicode定义的字符属性 |
| re.X | re.VERBOSE详细模式 | 这个模式下正则表达式可以是多行,忽略空白字符,并可以加入注释。 |
1 | # 用 ^ran 固定样式开头,我是匹配不到第二行的 ran to you 的,所以我们得加上一个 re.M flag。 |
1 | # 如果你想用多种 flags,也是可以的, |
小案例
这个问题就是针对文件夹内所有的文件,将里面提到的 huangming98.github.io 改成 huangm.cn。
首先需要简化问题,简化出来的话,其实就是要有三个步骤。
- 遍历所有的文本文件
- 读取文件中文本字段
- 替换掉特定字段
1 | import os |
3.3序列化数据传输(Json and Pickle)
序列化(Serialization):把不同类型的数据打包保存在电脑硬盘中,或者用于数据的传输(云服务)。
Pickle
1 | import os |
Json
JSON (JavaScript Object Notation)是用于存储和交换数据的语法。最初是用 JavaScript 对象表示法编写的文本,但随后成为了一种常见格式,被包括Python在内的众多语言采用。
1 | import json |
json.dumps()的一些参数 (重点)
因为dumps编码以后的json格式输出比较的紧凑,如果不止一行看起来就不是特别好看,就像一堆乱码似的。所以,就推出了一些可选参数来让json码的可读性更高。
1 | json.dumps(obj, sort_keys=False, skipkeys=False, ensure_ascii=True, check_circular=True, |
Pickle 与 Json 对比如下:
| 对比 | Pickle | Json |
| :—————: | :—————————————: | :————————————————————-: |
| 存储格式 | Python 特定的 Bytes 格式 | 通用 JSON text 格式,可用于常用的网络通讯中 |
| 数据种类 | 类,功能,字典,列表,元组等 | 基本和 Pickle 一样,但不能存类,功能 |
| 保存后可读性 | 不能直接阅读 | 能直接阅读 |
| 跨语言性 | 只能用在 Python | 可以跨多语言读写 |
| 处理时间 | 长(需编码数据) | 短(不需编码) |
| 安全性 | 不安全(除非你信任数据源) | 相对安全 |
python 相关连接
1. python基础
2. python100天
3.虚拟环境配置
1 | conda create -n rich python=3.7 #创建环境 |
4. requirements
1 | pip install -r requirements.txt |
例如
1 | pytest==6.2.5 |
- python图形界面示例
5. mmdetetion
5.1 教程
1 | python -m torch.distributed.launch --nproc_per_node=1 --master_port=29500 tools/analysis_tools/benchmark.py $cofig $checkpoint --launcher pytorch |
5.3 分布式训练
1 | Export CUDA_VISIBLE_DEVICES=”0,1,2,3” |
5.4 训练
1 | Export CUDA_VISIBLE_DEVICES=2 |
5.5 测算模型参数量和计算量
1 | python tools/analysis_tools/get_flops.py ${CONFIG_FILE} [--shape ${INPUT_SHAPE}] |
5.6 指定GPU运行
1 | export CUDA_VISIBLE_DEVICES=1 |
5.7. Git
1 | git init (初始化本地仓库) |
- 冲突
1 | git add . |