【个人笔记】python
Title: Python学习
1 基本用法
输入输出
格式化输出
-
python的格式化输出
str1 = "num: {}".format(123) str1 = "num: {:<44}".format(123) str1 = "num: {:^20}".format(123)
-
{}
与.format()
:占位符、格式控制语句(替换{}
的内容); -
{:<44}
、{:^20}
:<
表左对齐、>
表右对齐,数字是占位符的宽度;此处
{:<44}
表示一个宽度为44的左对齐占位符,{:^20}
表示一个宽度为20的居中对齐占位符。
-
数组
创建
-
创建指定大小
# 一维 a = [1] *10 ; # 大小位10,初始化全1 # 二维 a = [ [1 for i in range(3)] for h in range(4) ] # 大小4行3列的二维矩阵 # a= [ [1,1,1,], [1,1,1,], [1,1,1], [1,1,1] ]
添加新元素
-
先创建空间再添加
list = [1, 2, 3] list.append("") # 不append直接list[4]会报IndexError list[4] = 4
错误的方式:直接索引“尾部溢出index”来添加新元素 ❌
列表推导式
-
英文称呼:List Comprehension
-
语法:
B = [a for a in A if a]
- 含义:对于列表A中的每个元素a,如果a的值为真(非零、非空、非None),则将其添加到新列表中。新列表为B.
- 优点:比普通for语句在py中运行的快。因为推导式是编译到C语言级别,而普通for语句是解释型。
- 缺点:更耗内存。
字符串
-
串拼接
注意:串和数字拼接,必须手动把数字变量用
str()
转为字符,否则会报error。 -
串分割
list = str1.split(' ')
可以化字符串为列表(按间隔符' '
)。
文件读写
常规读/写
-
写文件
filename = '???' with open(filename, 'w') as fp:fp.write("...str...")
文件指针操作
-
file.seek(offset, 方向
用法- 细节见此ref:文件操作中file.seek()方法
- offset的单位:字符数(字节)
size = file.tell()
返回文件指针的当前位置,单位-字符数(字节)
上述单位,不以
open("xxx", 'r')
还是rb
为转移.-
file.seek()
的使用注意事项若file是以
'r'
打开的,则不能随意用.seek(offset数, 0/1/2)
,因为按字符打开的文本,其文本的编码字节与字符的内容没有一一对应的关系,用.seek()
就没法精确按数量移动文件指针(除非调用.tell()
函数返回offset的值),用自定义的数值进行.seek()
跳转,会出现随机、未知的错误.我就出现了使用
file.seek(负数, 2)
的报错:io.UnsupportedOperation: can’t do nonzero end-relative seeks.故用
.seek()
函数时,最好用'rb'
的二进制比特流来打开文本。
-
从文本尾部开始读取,检索关键字
-
文本必须以二进制流的形式读取、再用seek()函数跳转指针位置、读取比特流后得编码。
-
Demo
with open(filename, 'rb') as file:file.seek(-20000, 2)content = file.read()str_content = content.decode('utf-8', errors='ignore')if 'fatal' in str_content:return 1else:return 0
-
将文件以只读、二进制的形式打卡
-
文件指针跳转到末尾20000个字节处
utf-8的编码,字符占1,2,4字节,选其倍数即可。
-
读取剩下的比特流信息
-
编码为utf-8文本
-
查看字符串是否在文本中。
-
-
-
在文件开头插入新内容
注意:跳到开头插入写,默认是覆写。
-
做梦:提前用file.tell()获得行开头指针的偏移pos,再用readline()读一行,后用file.seek(index)使指针跳回并用file.write(str)实时修改。
-
现实:文件指针跳转到行头对内容进行修改时,不会自适应进行“插入”或“删减”空间。覆写的字节数不一致时,会使得原文本的尾巴滞留,或覆盖了第二行的文本。
-
正确方式:直接在python数组中写好后,整体文本重写file中.
-
2 re库用法
-
正则表达式
(.*?)
是啥意思.
是名词,表示“任何字符”*
是修饰符,表示“任何个数”?
是修饰符,表示“尽量少”。故
.*?
表示,可以匹配任意长度的词儿,但尽可能少的去匹配。 -
串
abc def gg.run
,要提取gg.run
的gg
,正则怎么写?r"(.*?)\.run"
不行,会匹配所有(为啥,我还不知道❓)r"(\w+)\.run"
可以。✔️最终python代码:
ans = (re.findall(r"(\w+)\.run", string1))[0]
即可,返回的是串;不加[0]
返回的是类似json的对象。 -
如何用re库匹配 ‘abc_123_def’ 或 ‘abc_456_def’ 或 ‘abc_123_defgggg’ 或 ‘abc_456_defgggg’?
A:
r 'abc_[123|456]_def(gggg)*'
错的!这是java中的正则语法!
python中,[]
会匹配其内的所有字符,按“个”进行或选择的。根本不是单词我去。
而用:ans = re.findall(r 'abc_(123|456)_def(gggg)*', tmp_str)
那么ans
会是括号内的值.
正确答案:ans = re.search(r 'abc_(123|456)_def(gggg)*', tmp_str)
-
re库的
[]
,()
咋用? 尤其是()
,一会儿是说“提取”功能,一会儿是说“可选匹配)功能…❓
-
re库的
""
的作用,在r'...串...'
内添加一个双引号,直接就匹配失效了,为啥??❓
-
re.match()
是从头开始匹配我去。
想“从中间匹配都没问题”的话,得用re.search()
-
re.findall(r'...()...')
得到的是括号里的内容。如果要得到完整的串,得用:
ans = re.search(r'...()...')
,然后用ans.group(0)
进行输出,无法用 ans[0]哈,会error
若没找到,ans = None
-
findall()
返回的结果,里面的字符串信息,可以用ans[0]
获取;没有则为""
-
re.search()
返回的结果,里面的字符串信息,只能用ans.group(0)
获取;没有则为None
3 多进程
-
Popen.poll() 返回值问题
-
作用:用Popen实现多进程,如:回归测试、VCS仿真。
-
返回值:
-
none
:还在运行; -
0:正常结束;
-
其他数字:fatal.
负数,是 fatal signal错误标志。
-
ref: python popen函数讲解
-
4 工具内容
-
python确定程序运行时间
import time start_t = time.time() end_t = time.time() print("time: ", ent_t - start_t, " s.")
-
python3打印不同颜色的字体
print("\33[1;36m ...字符串... \033[0m") print("\33[1;33m ...字符串... \033[0m") print("\33[1;31m ...字符串... \033[0m")
5 python 2与3区别
-
print
-
同:
print
皆默认换行; -
异:
python2若不想默认换行,可用
print(),
加个逗号;
python3若不想默认换行,可用print("...", end="")
-
6 other代码参考
-
自动化make:
作用:重复make。把每次的log存下来求平均值,最后输出。
# this is python2 import os import os.path import sys# Paraneters: simulation numbers sim_num = 50; mode = 0;IN_FILE = ""; OUT_FILE = ""; if(mode == 0):IN_FILE = "PR.log";OUT_FILE = "average_PR.log"; elif(mode == 1):IN_FILE = "SGA.log";OUT_FILE = "average_SGA.log"; else:IN_FILE = "cg_record.log";OUT_FILE = "average.log"; print("My python is beginning..."); log_len = 100 + 1; cg_value = [0] * log_len; for i in range(sim_num):# run the simulationos.system("make");# read the log and add the CG value to the result list. PR_log_file = open(IN_FILE,'r');j = 0;try:lines = PR_log_file.readlines()for line in lines:cg_value[j] += float(line.strip());j = j+1;if(j==log_len):break;finally:PR_log_file.close();print( "\n\n\n" + str(i) + "-th sim/" + str(sim_num) + " done!\n\n"); # show the result print("\n\nShow the Average Result:"); for i in range(log_len):cg_value[i] /= sim_num;print(cg_value[i]);# write the result try:fp = open(OUT_FILE,'w');for value in cg_value:fp.write(str(value) + "\n"); finally:PR_log_file.close();print(OUT_FILE + " has generated.");
-
python如何写shell/python如何调用make或makefile
调用shell的本质就是:
os.system("make");
import os import os.path import sys#sys.exit(0); ######################################################################################################################### # # 本脚本的作用是:通过配置必要的信息,用python来生成makefile。(技术支持:www.guimigame.com) # @FILENAME 运行脚本输出makefile文件名称 # @BIN 生成可运行文件名称 # @SUFFIX 源文件后缀 # @ROOTPATH “根”文件夹路径(脚本工作文件夹的上一层) # @PWD 当前工作文件夹 # @WD 工作文件夹。假设程序有多个工作文件夹请一一用append加上 # @BINDIR 可运行文件输出文件夹 # @OBJDIR 中间文件输出文件夹 # @INCROOTPATH 头文件包括路径的“根路径”,方便INCPATH的编写 # @LIBROOTPATH 包括库的“根”路径。方便LIBS的编写 # @INCPATH 头文件包括路径 # @SYSLIBS 包括的系统库 # @LIBS 编译程序须要包括的库 # @CXX 一般填写gcc/g++ # @FLAGS gcc/g++的编译标志 # ######################################################################################################################### FILENAME = 'makefile'; BIN = "DatabaseServer"; SUFFIX = ".cpp";ROOTPATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__))); PWD = os.getcwd();WD = []; WD.append(PWD); WD.append(ROOTPATH + "/common");BINDIR = PWD + "/Bin/"; OBJDIR = BINDIR + "obj/";INCROOTPATH = "-I " + ROOTPATH; LIBROOTPATH = "-L " + ROOTPATH;INCPATH = INCROOTPATH + "/common" + " " + INCROOTPATH + "/lib/include"; SYSLIBS = " -lmysqlclient -lpthread" LIBS = LIBROOTPATH + "/lib/linux " + "-lTimeManager -lServerConfig -lGameSocket -lCommon -lTinyxml" + SYSLIBS; CXX = "g++"; FLAGS = '-g -Wall';######################################################################################################################### # # 下面不须要再配置 # #########################################################################################################################OBJFILE = ''; OBJ2SRC = [];SOURCES = "";def SearchFiles(path):global OBJFILE;global OBJ2SRC;global SOURCES;global SUFFIX;listFile = os.listdir(path);for file in listFile:if os.path.isdir(os.path.join(path, file)):SearchFiles(os.path.join(path, file));elif file.endswith(SUFFIX) > 0:OBJFILE = file;OBJFILE = OBJFILE.replace(SUFFIX,'.o');OBJ2SRC.append([OBJDIR + OBJFILE,path + "/" + file]);SOURCES += path + "/" + file + " ";for dir in WD:SearchFiles(dir);if os.path.exists(FILENAME):os.remove(FILENAME);f = open(FILENAME,'w');f.write("PWD = " + PWD + "\n"); f.write("CXX = " + CXX + "\n"); f.write("INCPATH = " + INCPATH + "\n"); f.write("LIBS = " + LIBS + "\n"); f.write("BINDIR = " + BINDIR +"\n"); f.write("OBJDIR = " + OBJDIR + "\n"); f.write("BIN = " + BIN + "\n"); f.write("SOURCES = " + SOURCES+ "\n"); f.write("SOURCEFILES = $(notdir $(SOURCES))\n"); f.write("OBJECTS = $(addprefix $(OBJDIR), $(patsubst %.cpp,%.o,$(SOURCEFILES)))\n"); f.write("FLAGS = " + FLAGS + "\n"); f.write("\n");f.write("all:makedir $(OBJECTS)\n"); f.write(" $(CXX) $(FLAGS) $(INCPATH) -o $(BIN) $(OBJECTS) $(LIBS);\n"); f.write("\n");f.write("makedir:\n"); f.write(' $(shell if [ -n "$(OBJDIR)" -a ! -e "$(OBJDIR)" ];then mkdir -p $(OBJDIR); fi)\n'); f.write(' $(shell if [ -n "$(BINDIR)" -a ! -e "$(BINDIR)" ];then mkdir -p $(BINDIR); fi)\n'); f.write("\n"); for val in OBJ2SRC:f.write(val[0] + ":" + val[1] +"\n");f.write(" rm -f $@\n");f.write(" $(CXX) -fpic -c $(INCPATH) $< -o $@\n");f.write("\n");f.close();os.system("make"); os.system("mv " + BIN + " " + BINDIR); os.system("cd " + OBJDIR + ";rm -f *.o");