逻辑控制
条件语句
if...else 语句
def is_car(car):
if car:
print(car)
else:
print("no car")
# 函数测试
car = "www"
is_car(car) # 'www'
car = ""
is_car(car) # 'no car'
car = None
is_car(car) # 'no car'if...elif...else 语句
s1 = "Audi"
s2 = "AuDi"
if s1 == s2:
print("equl")
else:
if s1.lower() == s2.lower():
print("same char")
elif s1.lower() != s2:
print("lower not equl")
else:
print("No")if and 、if or 语句
age1 = 12
age2 = 20
if (age1 >= 18) and (age2 >= 18):
print("all")
if (age1 >= 18) or (age2 >= 18):
print("one")if not 语句
age = 12
if not (age >= 18):
print("small")
循环语句
for 语句
for i in range(1, 10, 2):
print(i)while 语句
num = 0
while num <= 10:
num += 3
print(num)continue 语句
# for...continue
for i in range(1, 10):
if i % 2 == 0:
continue
# continue:忽略余下代码,返回循环开头继续循环
# 即不会再执行下一行 print(i),直接返回循环开头继续循环
print(i)# while...continue
num = 0
while num <= 10:
num += 1
if num % 2 == 0:
continue
# continue:忽略余下代码,返回循环开头继续循环
# 即不会再执行下一行 print(num),直接返回循环开头继续循环
print(num)break 语句
# for...break
for i in range(1, 10, 2):
if i == 7:
break
# break:忽略余下代码,直接退出循环
print(i)# while...break
while True:
city = input("Please enter a city: ")
if city == 'quit':
break
# break:忽略余下代码,直接退出循环
else:
print( city.title() )
异常处理语句
try 语句
try...except
# 基本语法格式
# try模块(有且仅有一个)
# except模块 (至少一个,可多个),每个 except代码块 都可同时处理多种异常
try:
# 可能产生异常的代码块
except [ (Error1, Error2, ... ) [as e] ]:
# 处理 Error1, Error2, ... 类型异常的代码块
except [ (Error3, Error4, ... ) [as e] ]:
# 处理 Error3, Error4, ... 类型异常的代码块
except [Exception]:
# 处理其它所有异常类型的代码块
# 该格式中,[] 括起来的部分可有可无,其中:
# (Error1, Error2,...)(Error3, Error4,...):可选,具体的异常类型,如 IndexError(下标越界)、ValueError(数值异常) 等
# [as e]:可选,给 异常类型 起别名 e ,方便在 except模块 中调用该异常类型
# [Exception]:可选,代指所有异常类型,通常用于最后一个 except模块# 异常处理流程
# Step1: 捕获异常
# 执行 try模块,如果执行过程中出现异常,系统自动生成异常类型,并将该异常提交给 Python 解释器
# Step2: 处理异常
# Python 解释器收到异常对象后,寻找能处理该异常对象的 except模块
# (1)找到合适 except模块 :将该异常对象交给该 except 块处理
# (2)找不到合适 except模块 :程序终止运行,Python 解释器退出
# 总结:
# 只要代码执行出现异常,就会生成对应的异常对象
# 但是只有 try模块中的代码 运行时发生的异常,才会提交给 except模块
# 而且只有 except模块 可以 匹配 到该异常时,才能处理异常
# 否则程序都将终止运行# 示例1
try:
print("进行除法运算")
# 除数不能为0,程序运行到此处会发生错误
ans = 5 / 0
print( "运算结果:", ans )
# 使用 ZeroDivisionError 来 匹配 异常
except ZeroDivisionError:
print("发生异常:[除0错误] 除数不能为 0")
except :
print("发生异常:[未知错误]")
print("程序继续运行至此")
# 运行结果:
# 进行除法运算
# 发生异常:[除0错误] 除数不能为 0
# 程序继续运行至此# 示例2
try:
print("进行除法运算")
# 除数不能为0,程序运行到此处会发生错误
ans = 5 / 0
print( "运算结果:", ans )
# 使用 ValueError, ArithmeticError 来 匹配 异常,即 except模块 可同时捕获这2种异常
except (ValueError, ArithmeticError):
print("发生异常:[数值错误] 或 [算术错误]")
except :
print("发生异常:[未知错误]")
print("程序继续运行至此")
# 运行结果:
# 进行除法运算
# 发生异常:[数值错误] 或 [算术错误]
# 程序继续运行至此# 在 示例2 中,虽然捕获了异常,但是只能判定是 数值异常 或 计算异常
# 如果想要知道具体是那种异常,则可以返回异常类型具体信息
# 示例3
try:
print("进行除法运算")
# 除数不能为0,程序运行到此处会发生错误
ans = 5 / 0
print( "运算结果:", ans )
# 给 异常类型 起别名 e ,方便调用该异常类型具体信息
except Exception as e:
# 异常的 错误编号 和 描述字符串
print( e.args )
# 异常信息(不包括异常信息的类型)
print(str(e))
# 较全的异常信息(包括异常信息的类型)
print(repr(e))
print("程序继续运行至此")
# 运行结果:
# 进行除法运算
# ('division by zero',)
# division by zero
# ZeroDivisionError('division by zero')
# 程序继续运行至此try...except...else
# 基本语法格式
# try模块(有且仅有一个)
# except模块 (至少一个,可多个),每个 except代码块 都可同时处理多种异常
# else模块(有且仅有一个)
try:
# 可能产生异常的代码块
except [ (Error1, Error2, ... ) [as e] ]:
# 处理 Error1, Error2, ... 类型异常的代码块
except [Exception]:
# 处理其它所有异常类型的代码块
else:
# try模块 无异常时,接着执行的代码块
# 总结:
# else模块的代码,只有 try模块 无异常时,才会执行
# 即如果 try模块 捕获到异常,就算相应的 except模块 处理完异常,else模块 代码也不会执行
# 因此可以将 else模块 视为保护措施,即只有当 try模块 无异常时,才会继续执行的操作
# 以免前面发生了错误,却继续执行后续代码,导致更多的错误# 示例1
try:
print("进行除法运算")
ans = 5 / 2
except ValueError:
print("发生异常:[数值错误] 必须输入数值")
except ArithmeticError:
print("发生异常:[算术错误] 除数不能为 0 ")
else:
print( "运算结果:", ans )
print("程序继续运行至此")
# 运行结果:
# 进行除法运算
# 运算结果: 2.5
# 程序继续运行至此# 示例2
try:
print("进行除法运算")
# 除数不能为0,程序运行到此处会发生错误
ans = 5 / 0
except ValueError:
print("发生异常:[数值错误] 必须输入数值")
except ArithmeticError:
print("发生异常:[算术错误] 除数不能为 0 ")
else:
print( "运算结果:", ans )
print("程序继续运行至此")
# 运行结果:
# 进行除法运算
# 发生异常:[算术错误] 除数不能为 0
# 程序继续运行至此try...except...finally
# 基本语法格式
# try模块(有且仅有一个)
# except模块 (可无,可有,可多个),每个 except代码块 都可同时处理多种异常
# else模块(可无,可有,最多一个)
# finally模块(有且仅有一个)
try:
# 可能产生异常的代码块
except [ (Error1, Error2, ... ) [as e] ]:
# 处理 Error1, Error2, ... 类型异常的代码块
except [Exception]:
# 处理其它所有异常类型的代码块
else:
# try模块 无异常时,接着执行的代码块
finally:
# 无论 try模块 是否发生异常,最终都会执行的代码块
# 总结:
# 当 try模块 未发生异常, else模块、finally模块可以执行
# 当 try模块 发生异常, except模块、finally模块可以执行
# 当 try模块 发生异常,except模块 不能处理时,finally模块 依然可以执行
# 即无论如何,finally模块 都会执行
# 这个特性在某些情况下会有很大的作用,如:
# python的回收机制只能自动回收变量、类对象占用的内存,而无法自动关闭文件、关闭数据库连接等
# 因此如果在 try模块 中打开了一些物理资源(文件、数据库连接等),由于这些资源必须手动回收,所以这些回收操作通常放在 finally模块 中# 示例1:try模块 未发生异常
try:
print("进行除法运算")
ans = 5 / 2
except ValueError:
print("发生异常:[数值错误] 必须输入数值")
except ArithmeticError:
print("发生异常:[算术错误] 除数不能为 0 ")
else:
print( "运算结果:", ans )
finally:
print("无论如何都会运行我")
print("程序继续运行至此")
# 运行结果:
# 进行除法运算
# 运算结果: 2.5
# 无论如何都会运行我
# 程序继续运行至此# 示例2:try模块 发生异常
try:
print("进行除法运算")
# 除数不能为0,程序运行到此处会发生错误
ans = 5 / 0
except ValueError:
print("发生异常:[数值错误] 必须输入数值")
except ArithmeticError:
print("发生异常:[算术错误] 除数不能为 0 ")
else:
print( "运算结果:", ans )
finally:
print("无论如何都会运行我")
print("程序继续运行至此")
# 运行结果:
# 进行除法运算
# 发生异常:[算术错误] 除数不能为 0
# 无论如何都会运行我
# 程序继续运行至此# 示例2:try模块 发生异常,且未处理异常
try:
print("进行除法运算")
# 除数不能为0,程序运行到此处会发生错误
ans = 5 / 0
finally:
print("无论如何都会运行我")
print("程序继续运行至此")
# 运行结果:执行完 finally模块 代码才报错退出
# 进行除法运算
# 无论如何都会运行我
# Traceback (most recent call last):
# ans = 5 / 0
# ZeroDivisionError: division by zeroraise 语句
# 基本语法格式
raise [exceptionName [(reason)]]
# 该格式中,[] 括起来的部分可有可无,其中:
# exceptionName:可选,指定抛出的异常名称
# reason:可选,异常信息的相关描述
# 如果可选参数全部省略,则 raise 会把当前错误原样抛出
# 如果仅省略 (reason),则在抛出异常时,将不附带任何异常描述信息
# 总结:raise 有 3 种常用用法
# raise:引发当前上下文中捕获的异常(如在 except模块 中),或默认引发 RuntimeError 异常
# raise [exceptionName]:引发执行类型的异常
# raise [exceptionName [(reason)]]:引发执行类型的异常,并附带异常的描述信息# 示例1:raise 语句通常结合 try except (else finally) 使用
try:
num = input("输入一个数字:")
# 判断输入是否为数字
if not num.isdigit():
raise ValueError("必须输入数字!")
except ValueError as e:
print( "发生异常:", repr(e) )
# 运行结果:
# 输入一个数字:a
# 发生异常: ValueError("必须输入数字!")
# 分析:
# 若输入非数字,会执行 raise 引发 ValueError 异常
# 且该异常位于 try模块 ,因此交由 except模块 处理
# 且从此 except模块 返回的详细错误信息中可见,错误类型正是raise 引发的异常# 示例2:无参数 raise
try:
num = input("输入一个数字:")
# 判断输入是否为数字
if not num.isdigit():
raise ValueError("必须输入数字!")
except ValueError as e:
print( "发生异常:", repr(e) )
raise
# 运行结果:
# 输入一个数字:a
# 发生异常: ValueError('必须输入数字!')
# Traceback (most recent call last):
# raise ValueError("必须输入数字!")
# ValueError: 必须输入数字!
# 分析:
# 这里重点关注位于 except模块 中的 raise
# 由于在其之前已经手动引发了 ValueError 异常
# 此时 无参数 的 raise 语句会再引发一次和 之前同类型 的异常# 示例3:无参数 raise
try:
num = input("输入一个数字:")
# 判断输入是否为数字
if not num.isdigit():
raise
except ValueError as e:
print( "发生异常:", repr(e) )
# 运行结果:
# 输入一个数字:a
# Traceback (most recent call last):
# raise
# RuntimeError: No active exception to reraise
# 分析:
# 如果之前没有引发过异常, 此时 无参数 的 raise 语句默认引发的是 RuntimeError 异常traceback模块
捕获异常信息显示在终端控制台
# 捕获异常信息显示在终端控制台
import traceback
def first_method():
second_method()
def second_method():
third_method()
def third_method():
raise ValueError("发生异常:[数值错误]")
def main():
first_method()
try:
main()
except Exception as e:
# 捕获异常,并将异常传播轨迹在 控制台 显示
traceback.print_exc()
# 运行结果:异常传播轨迹
# Traceback (most recent call last):
# File "test.py", line 17, in <module>
# main()
# File "test.py", line 14, in main
# first_method()
# File "test.py", line 5, in first_method
# second_method()
# File "test.py", line 8, in second_method
# third_method()
# File "test.py", line 11, in third_method
# raise ValueError("发生异常:[数值错误]")
# ValueError: 发生异常:[数值错误]捕获异常信息保存到日志文件
# 捕获异常信息保存到日志文件
import traceback
def first_method():
second_method()
def second_method():
third_method()
def third_method():
raise ValueError("发生异常:[数值错误]")
def main():
first_method()
try:
main()
except Exception as e:
# 捕获异常,并将异常传播轨迹 保存到 日志文件
fp = open('error_log.txt', 'a')
traceback.print_exc(file=fp)
fp.close()
# 运行结果:异常传播轨迹(存储在 error_log.txt)
# Traceback (most recent call last):
# File "test.py", line 17, in <module>
# main()
# File "test.py", line 14, in main
# first_method()
# File "test.py", line 5, in first_method
# second_method()
# File "test.py", line 8, in second_method
# third_method()
# File "test.py", line 11, in third_method
# raise ValueError("发生异常:[数值错误]")
# ValueError: 发生异常:[数值错误]捕获异常信息保存到内存
# 如果不想将异常信息写入日志文件
# 也可将异常信息暂时写入内存(StringIO),之后需要用到的时候再读出来
from io import StringIO
import traceback
def first_method():
second_method()
def second_method():
third_method()
def third_method():
raise ValueError("发生异常:[数值错误]")
def main():
first_method()
try:
main()
except:
# 捕获异常,并将异常传播轨迹 保存到内存
fp = StringIO()
traceback.print_exc(file=fp)
# 需要用到的时候,显示异常信息
print( fp.getvalue() )
fp.close()
# 运行结果:异常传播轨迹
# Traceback (most recent call last):
# File "test.py", line 17, in <module>
# main()
# File "test.py", line 14, in main
# first_method()
# File "test.py", line 5, in first_method
# second_method()
# File "test.py", line 8, in second_method
# third_method()
# File "test.py", line 11, in third_method
# raise ValueError("发生异常:[数值错误]")
# ValueError: 发生异常:[数值错误]assert 语句
# 基本语法格式
assert 条件表达式
assert 条件表达式, 描述信息
# 判断某个表达式的值
# 若值为真,则程序继续执行
# 若值为假,则报 AssertionError 异常错误
# 在功能上等同于:
# if 表达式:
# 继续执行
# else:
# 报 AssertionError 异常错误
# 注意:
# 当在命令行模式运行 Python 程序时
# 传入 -O(大写)参数,可以禁用 assert 语句# 示例1:
score = float(input("输入考试成绩:"))
# 断言分数是否正常
assert 0 <= score <= 100
# 只有当 0 <= score <= 100 时,才会继续执行
print( "考试成绩为:", score )
# 运行结果:
# 输入考试成绩:80
# 考试成绩为: 80.0# 示例2:
score = float(input("输入考试成绩:"))
# 断言分数是否正常
assert 0 <= score <= 100 , "分数不在 0-100 之间"
# 只有当 0 <= score <= 100 时,才会继续执行
print( "考试成绩为:", score )
# 运行结果:报 AssertionError 异常错误
# 输入考试成绩:120
# Traceback (most recent call last):
# assert 0 <= score <= 100 , "分数不在 0-100 之间"
# AssertionError: 分数不在 0-100 之间# 示例3:assert 语句通常结合 try except (else finally) 使用
try:
score = float(input("输入考试成绩:"))
# 断言分数是否正常
assert 0 <= score <= 100 , "分数不在 0-100 之间"
# 只有当 0 <= score <= 100 时,才会继续执行
print( "考试成绩为:", score )
except AssertionError as e:
print("输入成绩不正确:", e)
# 运行结果:
# 输入考试成绩:120
# 输入成绩不正确: 分数不在 0-100 之间pass 语句
# pass: 空语句,不做任何事,一般用于占位,为了保持程序结构的完整性
for str_i in 'Python':
if str_i == 'h':
pass
print("this is pass")
print("current str is: {}".format(str_i))# 忽略报错
try:
print("进行除法运算")
# 除数不能为0,程序运行到此处会发生错误
ans = 5 / 0
except:
pass
print("程序继续运行至此")
# 运行结果:
# 进行除法运算
# 程序继续运行至此
数据类型
数值型
整型(int)
i = 30
print(i) # 30
print( type(i) ) # <class 'int'>布尔型(bool)
B = True
b = False
print(B) # True
print( type(b) ) # <class 'bool'>浮点型(float)
f = 3.1415
print(f) # 3.1415
print( type(f) ) # <class 'float'>
round() 函数详解
round(number, ndigits=None)
number:要四舍五入的数字(可以是整数或浮点数)
ndigits(可选):保留的小数位数,默认为 0,即四舍五入到整数复数型(complex)
c = 1+2j
print( type(c) ) # <class 'complex'>
print( c.real ) # 实部 1.0
print( c.imag ) # 虚部 2.0
print( c.conjugate() ) # 共轭复数 (1-2j)数据类型转换
# 自动转换
# “窄”数据类型会自动转换为更“宽”的数据类型,如:
# int 会自动转化为 float 或 complex
# float 会自动转化为 complex
# int 1 转化为 float 再相加
f = 1 + 2.3
print( type(f) ) # <class 'float'>,type()函数用于数据类型鉴定# 强制转换
# int() 强制转化为 int
print( int(2.6) ) # 2
# float() 强制转化为 float
print( float(3) ) # 3.0
# complex(real, imag) 强制转化为 complex
print( complex(1, 2) ) # (1+2j)
字符串
字符串大小写、数字
name = "ADa love"
# 首字母大写
print( name.title() ) # 'Ada Love'
# 全大写
print( name.upper() ) # 'ADA LOVE'
# 全小写
print( name.lower() ) # 'ada love'
# 判断是否全大写、全小写、数字
old_str = "AERDadj12"
# old_str 是否全为大写字母,返回 True or False
if old_str.isupper():
print("A yes")
# old_str 是否全为小写字母,返回 True or False
elif old_str.islower():
print("a yes")
# old_str 是否全为数字,返回 True or False
elif old_str.isdigit():
print("1 yes")字符串首尾字符判断
判断首部
# 判断 首部
# str.startswith(char, beg=0, end=len(str)): 判断字符串 首部 是否为 指定字符char
# beg:字符串检测的 起始位置
# end:字符串检测的 结束位置
old_str = "this is an example string..."
print ( old_str.startswith('this') ) # True
print ( old_str.startswith('i', 5) ) # True
print ( old_str.startswith('is', 5, 9) ) # True判断尾部
# 判断 尾部
# str.endswith(char, start=0, end=len(str)): 判断字符串 尾部 是否为 指定字符char
# start:字符串检测的 起始位置
# end:字符串检测的 结束位置
old_str = "this is an example string..."
print ( old_str.endswith('string...') ) # True
print ( old_str.endswith('..', 5) ) # True
print ( old_str.endswith('g...', 5, 9) ) # False字符串首尾字符删除
删除首尾
# 删除 首尾
# str.strip(char): 移除字符串 首尾 指定字符char,中间部分不受影响
# 可以理解为生成的 新字符串 首或尾 不能带有 字符char
# 不改变原字符串,因此记得赋值
old_str = " ADa "
new_str = old_str.strip() # 'ADa',默认移除空格' '
print(new_str)
old_str = "abaqraa13pobaa"
new_str = old_str.strip('a')
print(new_str) # 'baqraa13pob',中间部分的a不受影响
old_str = "abaqraa13pobaa"
new_str = old_str.strip('ab')
print(new_str) # 'qraa13po',首尾的a,b均被删除删除尾部
# 只删除 尾部
# str.rstrip(char): 只移除字符串 尾部 指定字符char,其他部分不受影响
# 可以理解为生成的 新字符串 尾部 不能带有 字符char
# 不改变原字符串,因此记得赋值
old_str = " ADa "
new_str = old_str.rstrip()
print(new_str) # ' ADa',默认移除空格' '
old_str = "ADa\n"
new_str = old_str.rstrip('\n')
print(new_str) # 'ADa',删除尾部 换行符
old_str = "**this . Ada!,,ssqw***"
new_str = old_str.rstrip('*')
print(new_str) # '**this . Ada!,,ssqw',删除了尾部所有的*
old_str = "**this . Ada!,,ssqw***"
new_str = old_str.rstrip('w*.')
print(new_str) # '**this . Ada!,,ssq',w*均为尾随字符,但.不是
old_str = "**this . Ada!,,ssqw***"
new_str = old_str.rstrip('*,qsw')
print(new_str) # '**this . Ada!',*,qsw均为尾随字符字符串分割
# str.split(char): 将字符串按 指定字符char 分割为 列表
# 不改变原字符串,因此记得赋值
line_str = "loss 2.7 FPS 360"
line_list = line_str.split()
print(line_list) # ['loss', '2.7', 'FPS', '360'],默认按 空格' ' 分割
line_str = "loss:2.7; FPS:360."
line_list = line_str.split(':')
print(line_list) # ['loss', '2.7; FPS', '360.'],按':'分割
line_str = "loss:2.7; FPS:360."
loss_num = float(line_str.split(':')[1].split(';')[0])
print(loss_num) # 2.7,连续分割字符串拼接
# char.join(x): 将 列表x 中的元素按 指定字符char 拼接为字符串
char_list = ['a', 'b', 's', 'dfr']
new_str = "".join(char_list)
print(new_str) # 'absdfr',按 空字符'' 拼接
line_list = ['Add', 'Relu', 'Reduce']
line_str = ", ".join(line_list)
print(line_str) # 'Add, Relu, Reduce',按', '拼接
line_list = ['Add', 'Relu', 'Reduce']
line_str = ", ".join(i for i in line_list)
print(line_str) # 'Add, Relu, Reduce',效果同上
# 字符串的重复就更简单了,用的是 *号:
# *号后面接一个数字,代表重复次数,这里是把“数据”两个字重复了5次:
print(str1 * 5) # 数据数据数据数据数据字符串查找
# 方法一:
line = 'loss:2.7, FPS:360.'
if 'loss' in line:
loss_num = float(line.split(':')[1].split(',')[0])
else:
loss_num = ''
print(loss_num) # 2.7
# 需要在字符串中查找某一个字符出现的位置,例如:
# str5.find.('o')表示要找到变量str5中,字母o首次出现的位置:
str5 = 'Hello'
print('字母o首次出现的位置:',str5.find('o')) # 字母o首次出现的位置: 4# 方法二:正则化搜索
# re.search(char, x): 检查 字符char 是否包含在 字符串x 中
import re
line = 'loss:2.7, FPS:360.'
if re.search('loss', line):
loss_num = float(line.split(':')[1].split(',')[0])
else:
loss_num = ''
print(loss_num) # 2.7字符串替换
# 方法一:
# str.replace(old_char, new_char): 将 字符串 中的 所有old_char 替换为 new_char,当新字符串为空是,相当于
# 不改变原字符串,因此记得赋值
# 指定字符替换
old_str = "this is old string by old man"
new_str = old_str.replace('old', 'new')
print(new_str) # 'this is new string by new man'
# 指定位置替换
old_str = "this is old string by old man"
new_str = old_str.replace(old_str[-3:], 'people')
print(new_str) # 'this is old string by old people'# 方法二:
# re.sub(old_char, new_char, x): 将 字符串x 中的 所有old_char 替换为 new_char
# 支持正则表达式
import re
old_str = "this is old string by old man"
new_str = re.sub('old', 'new', old_str)
print(new_str) # 'this is new string by new man'
# 所有中文 替换为 空''
old_str = "HelloWorld!%13你好2356世界。。"
new_str = re.sub("[\u4E00-\u9FA5]", "", old_str)
print(new_str) # 'HelloWorld!%132356。。'
# 所有非中文 替换为 空''
old_str = "HelloWorld!%13你好2356世界。。"
new_str = re.sub("[A-Za-z0-9\!\%\[\]\,\.\、\,\。]", "", old_str)
print(new_str) # '你好世界'字符串统计
# str.count(char): 查找 字符串 中的 字符char 的个数
old_str = "acafns"
print( old_str.count('a') ) # 2
old_str = "abccabfrnsab"
print( old_str.count('ab') ) # 3字符串逆序
# str[::-1]
# 等同于 str[-1 : -len(str)-1 : -1]
# 从 -1 处,到 -len(str)-1 处,以 -1 为步长
old_str = "AbcDefG"
new_str = old_str[::-1]
print(new_str) # 'GfeDcbA'
# 字符串切片方法与列表相似字符串元素排列组合
def string_permutation(s):
"""
# 功能:字符串s 的所有字符经过 排列组合 生成新字符串
# 输入:
# s: 字符串s
# 输出:
# all_str_list: 所有可能的结果
"""
# 内置递归函数
def recursion(l, start):
"""
# 功能:递归求解 list 内元素经过 排列组合 后的结果
# 输入:
# l: 列表list
# start: 开始位置
# 输出:
# res: 所有可能结果
"""
if start == len(l):
# 结束递归,整合当前结果
# 将 l 中的每个元素拼接为字符串
res.append("".join(l))
else:
for i in range(start, len(l)):
# 第 i 和 第 start 下标的元素互换
l[i], l[start] = l[start], l[i]
# start+1 开始递归
recursion(l, start+1)
# 第 i 和 第 start 下标的元素互换
l[i], l[start] = l[start], l[i]
return res
# 将 s 转为 列表 l
l = list(s)
# 初始化最终结果
res = []
# start = 0 开始递归,并去重
return set( recursion(l, 0) )
# 函数测试
my_str = 'abb'
print( string_permutation(my_str) )
列表
列表创建、访问
# 方法一:直接赋值
old_list = ['dog', 'cat', 3, [1, 2], 5.26]
print(old_list[0]) # 'dog'
print(old_list[-1]) # 5.26# 方法二:列表解析
num_list = [num**2 for num in range(1,5)]
print(num_list) # [1, 4, 9, 16]# 方法三:序列转换为列表
old_str = "yes no"
print( list(old_str) ) # ['y', 'e', 's', ' ', 'n', 'o']列表修改
列表改值
old_list = ['dog', 'cat', 'pig']
old_list[0] = 'python'
print(old_list) # ['python', 'cat', 'pig']列表追加、插入
old_list = ['dog', 'cat', 'pig']
# 在列表末尾追加,,一次追加一个元素
old_list.append('cow')
print(old_list) # ['dog', 'cat', 'pig', 'cow']
#extend() 是列表(list)的一个方法,用于将一个可迭代对象(如另一个列表、元组、集合等)中的所有元素添加到当前列表的末尾(不能是整数,不是可迭代对象)。与 append() 方法不同,后者是将整个对象作为一个元素添加到列表中
lst_test = [2, 3, 4, 6]
lst_test.extend([10, 15])
print(lst_test) # 输出:[2, 3, 4, 6, 10, 15]
# 在列表位置 1 处插入,一次插入一个元素
old_list.insert(1, 'wolf')
print(old_list) # ['dog', 'wolf', 'cat', 'pig', 'cow']
#add方法,两个列表相加,元素会新增进去,元素不会相加(让列表中的元素对应相加,可以使用zip函数)
print([1, 2, 3] + [3, 4, 5])
[1, 2, 3, 3, 4, 5]列表删除元素
old_list = ['dog', 'cat', 'pig', 'cow', 'snake']
# 删除 指定位置 元素
del old_list[2]
print(old_list) # ['dog', 'cat', 'cow', 'snake']
del old_list[0:2]
print(old_list) # ['cow', 'snake']
# 弹出 指定位置 元素,并将弹出的元素赋值(列表已改变),默认弹出末尾元素
# 可以指定删除的位置n,list.pop(n)
popped_value = old_list.pop()
print(popped_value) # 'snake'
print(old_list) # ['dog', 'cat', 'pig', 'cow']
popped_value = old_list.pop(1)
print(popped_value) # 'cat'
print(old_list) # ['dog', 'pig', 'cow']# 删除 指定值(有重复值时,只删除第一个)
pets_list = ['dog', 'cat', 'fish', 'snake', 'cat', 'dog', 'cat']
pets_list.remove('cat')#list.remove() 根据指定元素删除,因此不能默认
print(pets_list) # ['dog', 'fish', 'snake', 'cat', 'dog', 'cat']
# 删除 指定值(使用循环,全部删除)
pets_list = ['dog', 'cat', 'fish', 'snake', 'cat', 'dog', 'cat']
while 'cat' in pets_list:
pets_list.remove('cat')
print(pets_list) # ['dog', 'fish', 'snake', 'dog']
# count()可以帮助我们很快速地统计某个元素在列表中出现的次数
print('1在列表中出现了多少次:',lst6.count(1)) # 1在列表中出现了多少次: 5列表排序
# 方法一:只能用于列表排序;改变原列表
# list.sort(key=None, reverse=False)
# key: 指定关键字进行排序(单个元素、多个元素、lambda表达式)
# reverse: (默认)False升序;True降序
# .sort返回值是 None
# 方法二:可用于任意可迭代对象:字符串、元组、列表、字典等;返回类型为列表;不改变原对象,因此记得赋值;会有额外空间花销
# sorted(iterable, key=None, reverse=False)
# iterable: 可迭代对象(字符串、元组、列表、字典等)
# key: 指定关键字进行排序(单个元素、多个元素、lambda表达式)
# reverse: (默认)False升序;True降序简单排序
# 方法一:
old_list = [3, 6, 1, 5]
# 升序(默认),改变原列表
old_list.sort()
print(old_list) # [1, 3, 5, 6]
# 降序,改变原列表
old_list.sort(reverse=True)
print(old_list) # [6, 5, 3, 1]# 方法二:
old_list = [3, 6, 1, 5]
# 升序(默认),不改变原列表,因此记得赋值
new_list = sorted(old_list)
print(new_list) # [1, 3, 5, 6]
# 降序,不改变原列表,因此记得赋值
new_list = sorted(old_list, reverse=True)
print(new_list) # [6, 5, 3, 1]
old_str = 'Python'
new_str = sorted(old_str)
print(new_str) # ['P', 'h', 'n', 'o', 't', 'y']
old_tup = (3, 6, 1, 5)
new_tup = sorted(old_tup)
print(new_tup) # [1, 3, 5, 6]
old_dic = {'A':3, 'E':6, 'C':1, 'B':5}
new_dic = sorted(old_dic.items())
print(new_dic) # [('A', 3), ('B', 5), ('C', 1), ('E', 6)]指定 一个关键字 排序
# 示例:按照 第3个元素(成绩) 排序
# 方法一:
old_list = [['juju', 19, 85],['fafa', 17, 96],['lala', 20, 77],['haha', 18, 85]]
old_list.sort(key=lambda x: x[2])
print(old_list) # [['lala', 20, 77], ['juju', 19, 85], ['haha', 18, 85], ['fafa', 17, 96]]
# 方法二:
old_list = [['juju', 19, 85],['fafa', 17, 96],['lala', 20, 77],['haha', 18, 85]]
new_list = sorted(old_list, key=lambda x: x[2])
print(new_list) # [['lala', 20, 77], ['juju', 19, 85], ['haha', 18, 85], ['fafa', 17, 96]]
# 方法三:
import operator
old_list = [['juju', 19, 85],['fafa', 17, 96],['lala', 20, 77],['haha', 18, 85]]
# itemgetter(i):获取第i元素值
old_list.sort(key=operator.itemgetter(2))
print(new_list) # [['lala', 20, 77], ['juju', 19, 85], ['haha', 18, 85], ['fafa', 17, 96]]
# 方法四:
import operator
old_list = [['juju', 19, 85],['fafa', 17, 96],['lala', 20, 77],['haha', 18, 85]]
# itemgetter(i):获取第i元素值
new_list = sorted(old_list, key=operator.itemgetter(2))
print(new_list) # [['lala', 20, 77], ['juju', 19, 85], ['haha', 18, 85], ['fafa', 17, 96]]# 示例:按照 字典长度 排序
old_list = [{'A':1, 'B':2}, {'C':3}, {'D':4, 'E':5, 'F':6}]
new_list = sorted(old_list, key=lambda x: len(x))
print(new_list) # [{'C': 3}, {'A': 1, 'B': 2}, {'D': 4, 'E': 5, 'F': 6}]# 示例:按照 对象的某个属性(如成绩) 排序
import operator
class Student:
def __init__(self, name, age, score):
self.name = name
self.age = age
self.score = score
def __repr__(self):
return repr((self.name, self.age, self.score))
student_objects = [
Student('juju', 19, 85),
Student('fafa', 17, 96),
Student('lala', 20, 77),
Student('haha', 18, 85)]
# attrgetter(attrname):获取对象某个属性值
print( sorted(student_objects, key=operator.attrgetter('score')) )
# [('lala', 20, 77), ('juju', 19, 85), ('haha', 18, 85), ('fafa', 17, 96)]
print( sorted(student_objects, key=lambda stu: stu.score) )
# [('lala', 20, 77), ('juju', 19, 85), ('haha', 18, 85), ('fafa', 17, 96)]指定 多个关键字 排序
# 统一顺序/逆序
# 示例:以 第3个元素(成绩) 顺序,再以 第2个元素(年龄) 顺序
# 方法一:
old_list = [['juju', 19, 85],['fafa', 17, 96],['lala', 20, 77],['haha', 18, 85]]
old_list.sort(key=lambda x: (x[2],x[1]))
print(old_list) # [['lala', 20, 77], ['haha', 18, 85], ['juju', 19, 85], ['fafa', 17, 96]]
# 方法二:
old_list = [['juju', 19, 85],['fafa', 17, 96],['lala', 20, 77],['haha', 18, 85]]
new_list = sorted(old_list, key=lambda x: (x[2],x[1]))
print(new_list) # [['lala', 20, 77], ['haha', 18, 85], ['juju', 19, 85], ['fafa', 17, 96]]
# 方法三:
import operator
old_list = [['juju', 19, 85],['fafa', 17, 96],['lala', 20, 77],['haha', 18, 85]]
# itemgetter(i):获取第i元素值
old_list.sort(key=operator.itemgetter(2,1))
print(new_list) # [['lala', 20, 77], ['haha', 18, 85], ['juju', 19, 85], ['fafa', 17, 96]]
# 方法四:
import operator
old_list = [['juju', 19, 85],['fafa', 17, 96],['lala', 20, 77],['haha', 18, 85]]
# itemgetter(i):获取第i元素值
new_list = sorted(old_list, key=operator.itemgetter(2,1))
print(new_list) # [['lala', 20, 77], ['haha', 18, 85], ['juju', 19, 85], ['fafa', 17, 96]]# 统一顺序/逆序
# 示例:单词排序(第1个字母相同,则根据第2个字母排序,以此类推)
word_list = ['cat', 'binary', 'big', 'dog']
new_word_list = sorted(word_list, key=lambda x: (x[0],x[1],x[2]))
print(new_word_list) # ['big', 'binary', 'cat', 'dog']# 统一顺序/逆序
# 示例:按照 对象的某个属性(如成绩) 排序
import operator
class Student:
def __init__(self, name, age, score):
self.name = name
self.age = age
self.score = score
def __repr__(self):
return repr((self.name, self.age, self.score))
student_objects = [
Student('juju', 19, 85),
Student('fafa', 17, 96),
Student('lala', 20, 77),
Student('haha', 18, 85)]
# attrgetter(attrname):获取对象某个属性值
print( sorted(student_objects, key=operator.attrgetter('score', 'age')) )
# [('lala', 20, 77), ('haha', 18, 85), ('juju', 19, 85), ('fafa', 17, 96)]
print( sorted(student_objects, key=lambda stu: (stu.score,stu.age)) )
# [('lala', 20, 77), ('haha', 18, 85), ('juju', 19, 85), ('fafa', 17, 96)]# 先逆序,再顺序
# 示例:先对 第3个元素(成绩) 降序 ,再对 第2个元素(年龄) 升序
# 由于排序具有 稳定性,即 值相等 时将保留其 原始顺序
# 因此可先对 第2个元素(年龄) 升序排序,然后再对 第3个元素(成绩) 降序排序
old_list = [['juju', 19, 85],['fafa', 17, 96],['lala', 20, 87],['haha', 18, 85]]
temp_list = sorted(old_list, key=lambda x: x[1])
print(temp_list) # [['fafa', 17, 96], ['haha', 18, 85], ['juju', 19, 85], ['lala', 20, 87]]
new_list = sorted(temp_list, key=lambda x: x[2], reverse=True)
print(new_list) # [['fafa', 17, 96], ['lala', 20, 87], ['haha', 18, 85], ['juju', 19, 85]]列表去重
不保留原位序
# 不保留原位序
old_list = ['Ada', 'Duk', 'Ada', 'Bob', 'Mary', 'Duk', 'Bob', 'Zid']
# 使用 集合set 获取去重后的元素
new_list = list(set(old_list))
print(new_list) # ['Zid', 'Duk', 'Bob', 'Ada', 'Mary']保留原位序
# 保留原位序
old_list = ['Ada', 'Duk', 'Ada', 'Bob', 'Mary', 'Duk', 'Bob', 'Zid']
# 先使用 集合set 获取去重后的元素
new_list = list(set(old_list))
print(new_list) # ['Mary', 'Duk', 'Ada', 'Zid', 'Bob']
# 再对 原列表的索引进行排序
# 即对于 new_list 的每个元素,查找其原先在 old_list 中的索引
# 如 'Mary' - 4, 'Duk' - 1, 'Ada' - 0, 'Zid' - 7, 'Bob' - 3
# 然后按照这个位序排序
new_list.sort(key=old_list.index)
print(new_list) # ['Ada', 'Duk', 'Bob', 'Mary', 'Zid']列表遍历
顺序遍历
# 顺序遍历
old_list = ['dog', 'cat', 'pig']
for animal in old_list:
print(animal)
# zip() 方法
# zip() 函数用于将多个可迭代对象中的元素配对组合成一个元组,然后返回一个由这些元组组成的迭代器。如果传入的可迭代对象长度不一致,那么 zip() 会以最短的对象为准进行配对
# 创建两个列表
list1 = [1, 2, 3]
list2 = ['a', 'b', 'c']
# 使用 zip() 将两个列表组合
zipped = zip(list1, list2)
print(list(zipped)) # 输出: [(1, 'a'), (2, 'b'), (3, 'c')]
# 如果列表长度不同
list3 = [1, 2, 3, 4]
list4 = ['a', 'b']
zipped = zip(list3, list4)
print(list(zipped)) # 输出: [(1, 'a'), (2, 'b')]
# enumerate() 方法
# enumerate() 函数用于将一个可迭代对象(如列表)组合为一个索引序列,这样可以在遍历时同时获取索引和对应的值。它返回的是一个枚举对象,通常与 for 循环一起使用
#创建一个列表
fruits = ['apple', 'banana', 'cherry']
# 使用 enumerate() 获取索引和值
for index, fruit in enumerate(fruits):
print(f"Index: {index}, Fruit: {fruit}")
# 输出:
# Index: 0, Fruit: apple
# Index: 1, Fruit: banana
# Index: 2, Fruit: cherry
# 可以指定起始索引
for index, fruit in enumerate(fruits, start=1):
print(f"Index: {index}, Fruit: {fruit}")
# 输出:
# Index: 1, Fruit: apple
# Index: 2, Fruit: banana
# Index: 3, Fruit: cherry逆序遍历
# 逆序遍历
# 方法一:
# list.reverse(): 将 列表 的元素按 位序 逆序;改变原列表
old_list = ['dog', 'cat', 'pig']
old_list.reverse()
print(old_list) # ['pig', 'cat', 'dog']
# 方法二:
old_list = ['dog', 'cat', 'pig']
new_list = []
while old_list:
new_list.append(old_list.pop())
print(new_list) # ['pig', 'cat', 'dog']列表切片
# list[a:b]: 选取列表索引为 a <= x < b 的所有元素,注意取不到b
old_list = ['dog', 'cat', 'pig', 'chick', 'fish']
print( old_list[1:3] ) # ['cat', 'pig']
print( old_list[:2] ) # ['dog', 'cat']
print( old_list[3:] ) # ['chick', 'fish']
print( old_list[:-1] ) # ['dog', 'cat', 'pig', 'chick']
print( old_list[:-2] ) # ['dog', 'cat', 'pig']
for x in old_list[:3]:
print(x)列表复制
切片复制
# 方法一:切片复制
# 此操作后,num_list_new 和 num_list 没有关系,改动变化也不会相互影响
num_list = [1, 3, 5, 7, 10]
num_list_new = num_list[:]
print(num_list_new) # [1, 3, 5, 7, 10]
num_list_new = num_list[1:-2]
print(num_list_new) # [3, 5]直接赋值
# 方法二:直接赋值
# 此操作后,num_list_wrong 和 num_list 共同变化
num_list = [1, 3, 5, 7, 10]
num_list_wrong = num_list
print(num_list_wrong) # [1, 3, 5, 7, 10]
num_list[2] = 'test'
print(num_list_wrong) # [1, 3, 'test', 7, 10]列表查找指定元素
old_list = ['dog', 'cat', 'pig']
if 'dog' in old_list:
print("yes")
if ('audi' not in old_list):
print("no")
if not ('audi' in old_list):
print('no')
# 查找元素索引位置
# index(某个元素值)可以帮助我们获取某元素在列表中的索引位置:
lst7 = ['a','b','c','d']
print(lst7.index('c')) # 2列表判断为空
old_list = []
if old_list:
print(old_list)
else:
print("empty")
字典
键值对的形式存在:字典通过键值对存储数据。键类似于索引,指向唯一的值。
本身是无序的:字典中的元素是无序的。我们不能像列表那样通过索引位置访问元素,而是通过键来访问。
唯一的键:每个键必须是唯一的,但值则可以重复。
字典创建、访问
# 方法一:新建 空字典 ,再逐个添加元素
old_dic = {}
old_dic['title'] = 'learn python'
old_dic['price'] = 99
print(old_dic) # {'title': 'learn python', 'price': 99}# 方法二:新建 空字典 ,再逐个添加元素(可记录字典 键-值对 的添加顺序)
from collections import OrderedDict
language_dic = OrderedDict()
language_dic['juju'] = 'python'
language_dic['fata'] = 'c'
print(language_dic) # OrderedDict([('juju', 'python'), ('fata', 'c')])# 方法三:新建 含值字典
book_dic = {'title': 'learn python',
'author': ['Enda', 'Fata'],
'pages': 128,
'price': 99
}
# 获取 指定键 的 值
v_title = book_dic['title']
print(v_title) # 'learn python'
# 获取 键 列表
key_list = book_dic.keys()
print(key_list) # ['title', 'author', 'pages', 'price']
# 获取 值 列表
value_list = book_dic.values()
print(value_list) # ['learn python', ['Enda', 'Fata'], 128, 99]
# 获取 键值对 列表
dic_list = book_dic.items()
print(dic_list) # [('title': 'learn python'),('author': ['Enda', 'Fata'])('pages': 128),('price': 99)]字典修改
字典增加
book_dic = {'pages': 128,
'price': 99
}
# 如果键是已经存在的,相当于是对这个键对应的值做了修改;如果这个键是新的,则为字典添加了一个新的元素(键值对)
book_dic['field'] = 'Computer'
print(book_dic) # {'pages': 128, 'price': 99, 'field': 'Computer'}字典删除
book_dic = {'title': 'learn python',
'pages': 128,
'price': 99
}
del book_dic['price']
print(book_dic) # {'title': 'learn python', 'pages': 128}字典改值
book_dic = {'title': 'learn python',
'pages': 128,
'price': 99
}
book_dic['price'] = 88
print(book_dic) # {'title': 'learn python', 'pages': 128, 'price': 88}字典值去重
# 使用 集合set 去重
book_dic = {'author_1': 'Enda',
'author_2': 'Enda',
'author_3': 'Coda',
'pages_1': 99,
'pages_2': 128,
'pages_3': 88,
'price': 88
}
print( book_dic.values() ) # ['Enda', 'Enda', 'Coda', 99, 128, 88, 88]
value_list_only = set(book_dic.values())
print(value_list_only) # {128, 99, 'Coda', 'Enda', 88}字典遍历
book_dic = {'title': 'learn python',
'author': ['Enda', 'Fata'],
'pages': 128,
'price': 99
}
# 遍历键:快(使用哈希表,用空间换时间)
for k in book_dic:
print(k) # 'title' 'author' ...
# 遍历键:慢(相当于列表遍历)
for k in book_dic.keys():
print(k) # 'title' 'author' ...
# 遍历值:慢(相当于列表遍历),不会对值进行去重
for v in book_dic.values():
print(v) # 'learn python' ['Enda', 'Fata'] 128 ...
# 遍历键 + 值:慢
for k, v in book_dic.items():
print(str(k) + ' -- ' + str(v))字典排序
# 可用于任意可迭代对象:字符串、元组、列表、字典等;返回类型为列表;不改变原对象,因此记得赋值;会有额外空间花销
# sorted(iterable, key=None, reverse=False)
# iterable: 可迭代对象(字符串、元组、列表、字典等)
# key: 指定关键字进行排序(单个元素、多个元素、lambda表达式)
# reverse: (默认)False升序;True降序按键排序
# 按 键 排序(排序后返回类型为列表)
old_dict = { "fafa": [17, 98], "juju": [20, 90], "huahua": [18, 94] }
new_list = sorted( old_dict.items() )
print( new_list ) # [('fafa', [17, 98]), ('huahua', [18, 94]), ('juju', [20, 90])]
# 恢复成字典
new_dict = dict(new_list)
print( new_dict ) # {'fafa': [17, 98], 'huahua': [18, 94], 'juju': [20, 90]}# 如果只需要 键
# 此时就相当于对列表排序,因为 old_dict.keys() 返回的就是 键列表
old_dict = { "fafa": [17, 98], "juju": [20, 90], "huahua": [18, 94] }
new_list = sorted( old_dict.keys() )
print( new_list ) # ['fafa', 'huahua', 'juju']按值排序
# 方法一:lambda
old_dict = { "fafa": 17, "juju": 20, "huahua": 18 }
# old_dict.items() 是 ('fafa', 17) 形式
# 因此 item[0] 代表键(如 'fafa'), item[1] 代表值(如 17)
new_list = sorted( old_dict.items(), key=lambda item:item[1] )
print( new_list ) # [('fafa', 17), ('huahua', 18), ('juju', 20)]
# 恢复成字典
new_dict = dict(new_list)
print( new_dict ) # {'fafa': 17, 'huahua': 18, 'juju': 20}old_dict = { "fafa": [17, 98], "juju": [20, 90], "huahua": [18, 94] }
# old_dict.items() 是 ('fafa', [17, 98]) 形式
# 因此 item[0] 代表键(如 'fafa'), item[1] 代表值(如 [17, 98]), item[1][1] 代表值的第2维(如 98)
new_list = sorted( old_dict.items(), key=lambda item:item[1][1] )
print( new_list ) # [('juju', [20, 90]), ('huahua', [18, 94]), ('fafa', [17, 98])]
# 恢复成字典
new_dict = dict(new_list)
print( new_dict ) # {'juju': [20, 90], 'huahua': [18, 94], 'fafa': [17, 98]}# 方法二:operator.itemgetter()
import operator
old_dict = { "fafa": 17, "juju": 20, "huahua": 18 }
# old_dict.items() 是 ('fafa', 17) 形式
# 因此 itemgetter(0) 代表键(如 'fafa'), itemgetter(1) 代表值(如 17)
new_list = sorted( old_dict.items(), key=operator.itemgetter(1) )
print( new_list ) # [('fafa', 17), ('huahua', 18), ('juju', 20)]
# 恢复成字典
new_dict = dict(new_list)
print( new_dict ) # {'fafa': 17, 'huahua': 18, 'juju': 20}# 方法三:zip 绑定 键-值 后再排序
old_dict = { "fafa": 17, "juju": 20, "huahua": 18 }
zip_list = list( zip(old_dict.keys(), old_dict.values()) )
new_list = sorted(zip_list)
print( new_list ) # [('fafa', 17), ('huahua', 18), ('juju', 20)]
# 恢复成字典
new_dict = dict(new_list)
print( new_dict ) # {'fafa': 17, 'huahua': 18, 'juju': 20}字典增强
Python库 - EasyDict
简介
Python 中默认的字典,仅支持通过dict[""]的方式访问键,导致代码中含有大量的""和[],且使用起来较为繁琐。
EasyDict 支持通过属性的方式去访问字典的值(同样也支持默认访问方式),且支持递归访问,可以让代码更加简洁易读。
安装与配置
# 安装(临时使用清华源)
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/ easydict
# 查看版本
import easydict
print(easydict.__version__) # 1.9访问字典值
# 默认字典
ori_dict = {'a':1,
'b':{'x':1, 'y':2}}
# 使用默认方式访问
print( ori_dict['b']['x'] ) # 1
# 作为属性访问
print( ori_dict.b.x ) # ERROR 报错:'dict' object has no attribute 'b'# EasyDict
from easydict import EasyDict
es_dict = EasyDict()
es_dict.a = 1
es_dict.b = {'x':1, 'y':2}
# 作为属性访问
print( es_dict.b.x ) # 1
# 使用默认方式访问
print( es_dict['b']['x'] ) # 1
元组
元组(tuple)是一个有序的不可变集合,一旦创建,其中的元素就不能修改。元组经常用于存储不应该被更改的数据集。
元组的特点:
不可变:元组一旦创建,就不能修改其内容。
有序:和列表一样,元组中的元素有固定的顺序。
支持不同数据类型:元组中可以包含不同类型的元素。
元组创建后,其单个元素不能 重新改动 或 重新赋值, 这是 元组 与 列表 的最大区别,其余方面 元组 和 列表 很相似
元组创建、访问
old_tup = (10, 500)
print(old_tup) # (10, 500)
print( old_tup[0] ) # 10
old_tup[1] = 30 # 错误
# 但元组变量可 整体 重新赋值
old_tup = (20, 500, 30) # 元组用圆括号 () 创建,元素用逗号分隔
print(old_tup) # (20, 500, 30)
集合
集合(set)是一个无序的、不重复的元素集。它主要用于成员关系测试、删除重复项以及数学上的操作(如并集、交集、差集)。 集合的特点和元组对应:
可变:集合可以添加或删除元素。
无序:集合中的元素没有顺序。
唯一:集合自动排除重复项。
集合创建
集合通过花括号 {} 或 set() 函数创建
# 集合set 是一个 无序、元素不重复 的序列
# 方法一:
new_set = {'apple', 'orange', 'apple', 'pear', 'orange'}
print(new_set) # {'orange', 'pear', 'apple'},会自动去重# 方法二:
new_set = set(['apple', 'orange', 'apple', 'pear', 'orange'])
print(new_set) # {'orange', 'pear', 'apple'},会自动去重
new_set = set('arabcbd')
print(new_set) # {'r', 'b', 'c', 'a', 'd'},会自动去重# 注意:创建 空集合 必须用 set() 而不是 {}
# 因为 {} 意为创建 空字典集合运算
a_set = set('arbcd')
print(a_set) # {'r', 'b', 'c', 'a', 'd'}
b_set = set('alczm')
print(b_set) # {'a', 'z', 'c', 'l', 'm'}
# a_set 与 b_set 的 并集
print(a_set | b_set) # {'m', 'r', 'b', 'z', 'l', 'c', 'a', 'd'}
# a_set 与 b_set 的 交集
print(a_set & b_set) # {'c', 'a'}
# a_set有 而 b_set无 的元素
print(a_set - b_set) # {'r', 'b', 'd'}
# 不同时包含于 a_set 和 b_set 的元素
print(a_set ^ b_set) # {'l', 'r', 'd', 'b', 'm', 'z'}集合添加元素
# 方法一:set.add(x)
old_set = {'orange', 'pear', 'apple'}
old_set.add('banana')
print(old_set) # {'apple', 'banana', 'pear', 'orange'}
# 若元素已存在,则不进行任何操作
old_set.add('apple')
print(old_set) # {'apple', 'banana', 'pear', 'orange'}# 方法二:set.update(x) x可为列表、元组、字典等
old_set = {'orange', 'pear', 'apple'}
old_set.update([1,3])
print(old_set) # {1, 3, 'apple', 'orange', 'pear'}
old_set.update([1,4], [5,6])
print(old_set) # {1, 3, 'apple', 'orange', 4, 5, 6, 'pear'}集合删除元素
# 方法一:set.remove(x) 若x不存在,则发生错误
old_set = {'orange', 'pear', 'apple'}
old_set.remove('apple')
print(old_set) # {'pear', 'orange'}
# 若元素不存在,则发生错误
old_set.remove('dog')
print(old_set) # 错误# 方法二:set.discard(x) 若x不存在,无视错误
old_set = {'orange', 'pear', 'apple'}
old_set.discard('apple')
print(old_set) # {'pear', 'orange'}
# 若元素不存在,则不会发生错误
old_set.discard('dog')
print(old_set) # {'pear', 'orange'}# 方法三:set.pop() 随机删除一个元素
old_set = {'orange', 'pear', 'apple', 'banana'}
delete_elem = old_set.pop()
# 多次执行,结果可能不同
print(delete_elem) # 'apple'
print(old_set) # {'banana', 'pear', 'orange'}集合清空
old_set = {'orange', 'pear', 'apple'}
old_set.clear()
print(old_set) # set()集合查找指定元素
old_set = {'orange', 'pear', 'apple'}
if 'apple' in old_set:
print("yes")
else:
print("no")
对象类型
函数
函数定义、调用
# 有默认值的参数必须放在最后(即其后不能存在无默认值的参数)
def book_money(book, price, num=5):
money = num * price
print(book + ': ' + str(money))
return money
# 使用默认值
pay_money = book_money('learn Python', 99)
# 位置实参
pay_money = book_money('learn Java', 99, 10)
# 关键字实参
pay_money = book_money(num=10, price=99, book='learn C')传递任意数量实参
# 传递任意数量实参(必须放在最后,代表剩下所有参数都赋值给它)
# 一个 * 代表创建名为 info 的 空元组
def person_info_1(name, age, *info):
print( "-->name: " + str(name) )
print( "-->age: " + str(age) )
for i in info:
print( "-->others: " + str(i) )
person_info_1('juju', 18, 'student', 'reading', 60) # 两个 ** 代表创建名为 info 的 空字典
def person_info_2(name, age, **info):
person = {}
person['name'] = name
person['age'] = age
for key, value in info.items():
person[key] = value
for key, value in person.items():
print( "-->" + key + ": " + str(value) )
person_info_2('juju', 18, work='student', like='reading', weight=50)
类
类定义、调用
class Person():
# 初始化属性
def __init__(self, name, age, work):
self.name = name
self.age = age
self.work = work
self.type = 'human'
self.show_info()
# 定义方法
def show_info(self):
print(self.type + ': ' + self.name + ' ' + str(self.age) + ' ' + self.work)
def next_year(self):
self.age += 1
print(self.name + ' ' + str(self.age))
def update_work(self, new_work):
self.work = new_work
jj = Person('juju', 18, 'student')
# 访问、修改属性
print( juju.age ) # 18
jj.age = 20
print( juju.age ) # 20
# 调用方法
jj.show_info() # human: juju 20 student
jj.next_year()
jj.update_work('teacher')
jj.show_info() # human: juju 21 teacher类继承
# 定义父类
class Person():
# 初始化属性
def __init__(self, name, age, work):
self.name = name
self.age = age
self.work = work
self.type = 'human'
# 定义方法
def show_info(self):
print(self.type + ': ' + self.name + ' ' + str(self.age) + ' ' + self.work)
def next_year(self):
self.age += 1
print(self.name + ' ' + str(self.age))
def update_work(self, new_work):
self.work = new_work
class Country():
def __init__(self, city='beijing'):
self.city = city
def show_city(self):
print('the city of the country is: ', self.city)
# 子类继承
class ChinesePerson(Person):
# 初始化属性
def __init__(self, name, age, work, language):
self.language = language
# 继承父类属性
super().__init__(name, age, work)
# 将实例化的类作为属性
self.country = Country('nanjing')
# 定义新方法
def speak(self, learn_language):
print('speak: ', self.language)
print('want to learn: ', learn_language)
# 覆盖重写父类方法
def show_info(self):
print(self.type + ': ' + self.name + ' ' + str(self.age) + ' ' + self.work + ' ' + self.language)
ff = ChinesePerson('fafa', 17, 'writer', 'chinese')
print(fafa.country.city) # 'nanjing'
ff.country.show_city() # 'the city of the country is: nanjing'
ff.speak('English') # ... want to learn: English
ff.show_info() # human: fafa 17 writer chinese
ff.next_year() # fafa 18
ff.update_work('coder')
ff.show_info() # human: fafa 18 coder chinese
数据格式
json
json(JavaScript Object Notation) 是一种轻量级的数据交换格式,主要用来持久化存储 Python 字典类型的数据。
python 数据转 json
import json
python_data = [ {'name': 'fafa', 'age': 18, 'job': 'coder', 'like': 'reading, games'} ]
# 正常输出
json_data = json.dumps(python_data)
print(json_data) # [{"name": "fafa", "age": 18, "job": "coder", "like": "reading, games"}]
# 格式化输出
json_data_format = json.dumps(python_data, sort_keys=True, indent=4, separators=(',', ': '))
print(json_data_format) # 如下:
[
{
"age": 18,
"job": "coder",
"like": "reading, games",
"name": "fafa"
}
]json 数据转 python
import json
json_data = '{"name": "fafa", "age": 18, "job": "coder", "like": "reading, games"}'
python_data = json.loads(json_data)
print(python_data) # {'name': 'fafa', 'age': 18, 'job': 'coder', 'like': 'reading, games'}json 文件读写
文件读取
# -*- coding: utf-8 -*-
# 文件读取
import sys
import json
def read_file_json(json_file, encode_type='utf-8'):
"""
# 功能:读取 json_file 文件内容
# 输入:
# json_file: 待读取文件路径
# encode_type: 文件编码方式
# 可选:'utf-8'(默认),最常用,包含中文字符
# 'gb18030',编码范围更广,包含少数民族字符
# 输出:
# file_content: 文件内容
"""
# 参数校验
if (encode_type != 'utf-8') and (encode_type != 'gb18030'):
print( "[ERROR] encode_type 错误:当前只支持 utf-8 或 gb18030" )
# 退出程序
sys.exit()
try:
# 读取文件
# (不推荐)使用 f = open(),使用后需要 close()
# (推荐)使用 with open() 创建运行时环境,执行完后自动退出,无需 close()
with open(json_file, encoding=encode_type, errors='ignore') as f:
file_content = json.load(f)
# 文件读入异常保护
except FileNotFoundError:
print( "[ERROR] 文件不存在:{}".format(json_file) )
# 退出程序
sys.exit()
else:
print( "[INFO] 已读取文件:{}".format(json_file) )
return file_content文件写入
# -*- coding: utf-8 -*-
# 文件写入
import os
import sys
import json
def write_file_json(file_content, json_file, write_type='w', del_file='no'):
"""
# 功能:将 file_content 内容写入 json_file 文件(.json)
# 输入:
# file_content: 待写入内容
# json_file: 待保存文件路径
# write_type: 文件写入方式
# 可选:'w'(默认),清空写入(会先初始化清空文件)
# 'a',追加写入(不会初始化清空文件,只在文件末尾追加)
# del_file: 如写入前文件已存在,是否强制删除
# 可选:'yes',强制删除
# 'no'(默认),询问用户是否删除
"""
# 参数校验
if not json_file.endswith('.json'):
print( "[ERROR] json_file 错误:当前只支持保存 .json 文件" )
# 退出程序
sys.exit()
if (write_type != 'w') and (write_type != 'a'):
print( "[ERROR] write_type 错误:当前只支持 w 或 a" )
# 退出程序
sys.exit()
if (del_file != 'yes') and (del_file != 'no'):
print( "[ERROR] del_file 错误:当前只支持 yes 或 no" )
# 退出程序
sys.exit()
# 先判断 json_file 是否存在
# 如果不存在,则直接生成新文件
if not os.path.isfile(json_file):
# 写入文件,依然推荐 with open()
with open(json_file, write_type, errors='ignore') as f:
json.dump(file_content, f)
print( "[INFO] 已生成新文件:{}".format(json_file) )
else:
# 如果强制删除旧文件
if del_file == 'yes':
# 先删除
os.remove(json_file)
# 写入文件,依然推荐 with open()
with open(json_file, write_type, errors='ignore') as f:
json.dump(file_content, f)
print( "[INFO] 旧文件已删除,已生成新文件:{}".format(json_file) )
else:
print("[WARNING] 文件已存在!是否用新文件覆盖旧文件?请输入 'yes' or 'no'.")
msg = "(input yes or no) >> "
delete_or_not = input(msg)
if delete_or_not == 'yes' or delete_or_not == 'y':
# 先删除
os.remove(json_file)
# 写入文件,依然推荐 with open()
with open(json_file, write_type, errors='ignore') as f:
json.dump(file_content, f)
print( "[INFO] 旧文件已删除,已生成新文件:{}".format(json_file) )
else:
print( "[INFO] 未生成新文件,旧文件已保留:{}".format(json_file) )函数测试
# 函数测试(先写入后读取)
num = [1, 3, 4, 6, 7, 9]
json_file = 'D:/FaramitaWorks/PythonWorks/test/num.json'
write_file_json(num, json_file)
new_num = read_file_json(json_file)
print(new_num) # [1, 3, 4, 6, 7, 9]# 函数测试(读取)
###### config.json 文件开始 ######
{
"my_info": {
"name": "fafa",
"age": 18,
"job": "coder",
"like": "reading, games"
}
}
###### config.json 文件结束 ######
json_file = 'D:/FaramitaWorks/PythonWorks/test/config.json'
json_content = read_file_json(json_file)
print(json_content["my_info"]) # {'name': 'fafa', 'age': 18, 'job': 'coder', 'like': 'reading, games'}
print(json_content["my_info"]["name"]) # 'fafa'
pickle
pickle 模块是 python 专用的数据持久化存储模块,可以存储 python 任何的复杂数据(如列表、元组、类等任何对象),但 pickle 文件只能通过 python 读取。
python 数据转 pickle
基于内存的二进制数据
# 对 数据 操作是复数,使用 pickle.dumps()
import pickle
python_data = ['Hello Python', {1, 2, 3}, None]
pickle_data = pickle.dumps(python_data)
print(pickle_data) # b'\x80\x04\x95\x1f\x00\x00\x00\x00\x00\x00\x00]\x94(\x8c\x0cHello Python\x94\x8f\x94(K\x01K\x02K\x03\x90Ne.'基于文件的二进制数据
# 对 文件 操作是单数,使用 pickle.dump()
# 操作文件时,要使用 wb(二进制) 模式,即只接收 bytes 类型的数据
import pickle
python_data = ['Hello Python', {1, 2, 3}, None]
file = "./data.pickle"
with open(file, 'wb') as f:
pickle.dump(python_data, f)pickle 数据转 python
基于内存的二进制数据
# 对 数据 操作是复数,使用 pickle.loads()
import pickle
python_data = ['Hello Python', {1, 2, 3}, None]
pickle_data = pickle.dumps(python_data)
print(pickle_data) # b'\x80\x04\x95\x1f\x00\x00\x00\x00\x00\x00\x00]\x94(\x8c\x0cHello Python\x94\x8f\x94(K\x01K\x02K\x03\x90Ne.'
# 读取 pickle_data
new_data = pickle.loads(pickle_data)
print(new_data) # ['Hello Python', {1, 2, 3}, None]基于文件的二进制数据
# 对 文件 操作是单数,使用 pickle.load()
# 操作文件时,要使用 rb(二进制) 模式,即只接收 bytes 类型的数据
import pickle
python_data = ['Hello Python', {1, 2, 3}, None]
file = "./data.pickle"
with open(file, 'wb') as f:
pickle.dump(python_data, f)
# 读取 pickle_data
with open(file, 'rb') as f:
new_data = pickle.load(f)
print(new_data) # ['Hello Python', {1, 2, 3}, None]持久化储存 python 类
import pickle
class Student:
def __init__(self, name, age):
self.name = name
self.age = age
def show_info(self):
print( "name:{} - age:{}".format(self.name, self.age) )
# 类实例化
stu = Student("JuJu", 18)
stu.show_info() # name:JuJu - age:18
# 存储类
file = "./student.pickle"
with open(file, 'wb') as f:
pickle.dump(stu, f)
# 读取类
with open(file, 'rb') as f:
new_stu = pickle.load(f)
new_stu.show_info() # name:JuJu - age:18
导入语句
导入模块、类、函数
模块、类、函数所在文件
# person_info.py 内容如下:
###### 文件开始 ######
# -*- coding: utf-8 -*-
def person_info_1(name, age, *info):
print( "-->name: " + str(name) )
print( "-->age: " + str(age) )
for i in info:
print( "-->others: " + str(i) )
def person_info_2(name, age, **info):
person = {}
person['name'] = name
person['age'] = age
for key, value in info.items():
person[key] = value
for key, value in person.items():
print( "-->" + key + ": " + str(value) )
###### 文件结束 ######导入方式
# 方式1:
import person_info
person_info.person_info_1('juju', 18, 'student', 'reading', 60)
person_info.person_info_2('juju', 18, work='student', like='reading', weight=50)# 方式2:
from person_info import person_info_1, person_info_2
person_info_1('juju', 18, 'student', 'reading', 60)
person_info_2('juju', 18, work='student', like='reading', weight=50)# 方式3:
import person_info as pi
pi.person_info_1('juju', 18, 'student', 'reading', 60)
pi.person_info_2('juju', 18, work='student', like='reading', weight=50)# 方式4:
from person_info import person_info_1 as pi_1
pi_1('juju', 18, 'student', 'reading', 60)# 方式5:(导入所有函数)
from person_info import *
person_info_1('juju', 18, 'student', 'reading', 60)
person_info_2('juju', 18, work='student', like='reading', weight=50)
模块搜索路径
# 将 父目录 添加到 Python搜索模块的路径集 中
# 以便可以导入父目录下(含所有子目录)的任何模块、函数、类等
# sys.path 为 Python模块搜索路径
# os.pardir 为 当前目录的父目录
import sys, os
sys.path.append(os.pardir)
文件操作
文件路径
获取当前信息
# 示例:当前执行代码文件为 '/home/test/test.py'
# 获取 当前执行代码文件所在文件夹 的路径(绝对路径)
# 如 B文件 中有代码 'os.getcwd()'
# 通过 A 调用 B,起始的是 A,则此时获取的是 A所在文件夹 的路径
import os
cwd_path = os.getcwd()
print(cwd_path) # '/home/test'# 示例:当前执行代码文件为 '/home/test/test.py'
# 获取 当前执行代码文件所在文件夹 的上级父目录 的路径(绝对路径)
# 其中:os.pardir 为 当前目录的父目录
import os
par_path = os.path.abspath(os.path.join(os.getcwd(), os.pardir))
print(par_path) # '/home'# 示例:当前执行代码文件为 '/home/test/test.py'
# 获取 当前执行代码文件 所在路径(绝对路径)
import os
print( __file__ ) # '/home/test/test.py'
print( os.path.abspath(__file__) ) # '/home/test/test.py'# 示例:当前执行代码文件为 '/home/test/test.py'
# 获取 当前执行代码文件 真实路径(绝对路径,而非软链接所在路径)
import os
print( os.path.realpath(__file__) ) # '/home/test/test.py'# 示例:当前执行代码文件为 '/home/test/test.py'
# 获取 当前模块 所在路径
# 即使 该模块所在文件 不是 执行代码文件
# 如 B文件 中有代码 'sys.argv[0]'
# 通过 A 调用 B,则此时获取的是 B文件 的路径
import sys
print( sys.argv[0] ) # '/home/test/test.py'# 获取 当前环境 所在路径
import sys
print( sys.path[0] ) # '/home/anaconda3/python38.zip'相对路径、绝对路径、真实路径
# 由 相对路径 转 绝对路径
import os
file_path = '/home/test'
print( os.path.abspath(file_path) ) # '/home/test'
file_path = '/home/test/../test'
print( os.path.abspath(file_path) ) # '/home/test'# 示例:当前代码文件为 '/home/test/test.py'
import os
print( os.getcwd() ) # '/home/test'
print( os.pardir ) # '..'
print( os.path.join(os.getcwd(), os.pardir) ) # '/home/test/..'
print( os.path.abspath(os.path.join(os.getcwd(), os.pardir)) ) # '/home'# 获取 指定文件 的真实路径(绝对路径,而非软链接所在路径)
import os
file_path = '/home/test/../test/test.py'
print( os.path.realpath(file_path) ) # '/home/test/test.py'拼接文件路径、文件名
# 方法一:
file_path = '/home/test'
file_name = 'file_test.txt'
file_with_path = file_path + '/' + file_name
print(file_with_path) # '/home/test/file_test.txt'# 方法二:
import os
file_path = '/home/test'
file_name = 'file_test.txt'
file_with_path = os.path.join(file_path, file_name)
print(file_with_path) # '/home/test/file_test.txt'解析文件路径、文件名
# 方法一:
import os
file_with_path = '/home/test/file_test.txt'
[file_path, file_name] = os.path.split(file_with_path)
print(file_path) # '/home/test',文件路径
print(file_name) # 'file_test.txt',文件名# 方法二:
import os
file_with_path = '/home/test/file_test.txt'
file_path = os.path.dirname(file_with_path)
file_name = os.path.basename(file_with_path)
print(file_path) # '/home/test',文件路径
print(file_name) # 'file_test.txt',文件名解析文件名、扩展名
import os
file_with_path = '/home/test/file_test.txt'
[file_path_name, file_extension] = os.path.splitext(file_with_path)
print(file_path_name) # '/home/test/file_test',文件路径+文件名
print(file_extension) # '.txt',扩展名
文件存在判断
文件路径存在
# 文件路径是否存在
import os
file_path = '/home/test'
print( os.path.exists(file_path) ) # True
file_with_path = '/home/test/test.txt'
print( os.path.exists(file_with_path) ) # True文件夹存在
# 指定 文件夹 是否存在(是否为文件夹)
import os
file_path = '/home/test'
print( os.path.isdir(file_path) ) # True
file_with_path = '/home/test/test.txt'
print( os.path.isdir(file_with_path) ) # False文件存在
# 指定 文件 是否存在(是否为文件)
import os
file_with_path = '/home/test/test.txt'
print( os.path.isfile(file_with_path) ) # True
file_path = '/home/test'
print( os.path.isfile(file_path) ) # False
文件遍历
遍历本层文件
# os.listdir(): 遍历文件夹本层文件
# 当前执行代码文件 所在文件夹 内的所有 文件+文件夹(不含子文件夹内文件)
import os
print( os.listdir() ) # ['test.py', 'test.txt', 'VBA文件夹', 'test.xlsm']# 指定路径 下的所有 文件+文件夹(不含子文件夹内文件)
import os
check_path = '/home/test/VBA'
print( os.listdir(check_path) ) # ['VBA.txt', 'VBA学习文件夹', 'VBA.xlsm']# 只接受 文件夹,不接受 文件
import os
file_path = '/home/test/test.txt'
print( os.listdir(file_path) ) # 报错遍历所有文件(含文件大小)
# -*- coding: utf-8 -*-
# 遍历文件夹所有文件(含子文件夹内文件),并按照文件大小排序
import os
import sys
def walk_files(folder_path):
"""
# 功能:遍历 folder_path 路径下的所有文件(含子文件夹),并按照文件大小排序
# 输入:
# folder_path: 待遍历的目标文件夹路径
# 输出:
# folder_list: 所有文件夹列表
# file_with_path_list: 所有文件列表
# file_with_path_list_size_sorted: 所有文件列表(按文件大小降序)
"""
# 首先去除尾部 / 或 \ 符号
folder_path = folder_path.rstrip('/\\')
# 如果 folder_path 存在且为文件夹
if os.path.isdir(folder_path):
file_with_path_list = []
file_with_path_list_size_sorted = []
folder_list = []
# root: 当前正在遍历的文件夹
# dirs: 该文件夹中所有文件夹名(不包括子文件夹),列表
# files: 该文件夹中所有文件名(不包括子文件夹),列表
for root, dirs, files in os.walk(folder_path):
# 遍历所有文件夹
for folder_name in dirs:
folder_list.append(os.path.join(root, folder_name))
# 遍历所有文件
for file_name in files:
file_with_path_list.append(os.path.join(root, file_name))
file_size = os.path.getsize(os.path.join(root, file_name))
file_with_path_list_size_sorted.append([file_size, os.path.join(root, file_name)])
# 按照文件大小排序(降序)
file_with_path_list_size_sorted.sort(key=lambda x: x[0], reverse=True)
# 打印所有 文件夹 / 文件
print("[INFO] 所有 文件夹 如下:")
for folder_name in folder_list:
print(folder_name)
print("\n[INFO] 所有 文件 如下:")
for file_name in file_with_path_list:
print(file_name)
print("\n[INFO] 所有 文件 如下(按文件大小降序):")
for file_name in file_with_path_list_size_sorted:
print(file_name)
else:
print( "[ERROR] 当前路径不存在 或 为文件:{}".format(folder_path) )
print( "[ERROR] 请重新输入文件夹路径!" )
# 退出程序
sys.exit()
return folder_list, file_with_path_list, file_with_path_list_size_sorted
# 函数测试
check_path = "D:/FaramitaWorks/PythonWorks/test"
all_folders, all_files, all_files_size_sorted = walk_files(check_path)
文件重命名
重命名文件
# os.rename(old_name, new_name) : 重命名 文件
# 如果 old_name 不存在,则报错
# 如果 new_name 已存在,则报错
import os
old_name = '/home/test/test.txt'
new_name = '/home/test/test_new.txt'
os.rename(old_name, new_name) 重命名文件夹
# os.rename(old_name, new_name) : 重命名 文件夹
# 如果 old_name 不存在,则报错
# 如果 new_name 已存在,则报错
import os
old_name = '/home/test'
new_name = '/home/test_new'
os.rename(old_name, new_name)
文件复制
复制文件
# 方法一:
# shutil.copy(old_file, new) : 复制 old_file 至 new(同时复制文件属性)
# old_file: 待复制文件路径(如果 不存在,则报错)
# new: 目标(文件路径 / 文件夹路径)
# 若 new 为 文件路径:
# 若 new 存在: 将 old_file 复制为 new 文件(相当于重命名)
# 若 new 不存在: 则报错
# 若 new 为 文件夹路径:
# 若 new 存在: 将 old_file 复制到 new 文件夹内
# 若 new 不存在: 会将文件夹 视为 无后缀的文件,进行复制
# 示例一:
import shutil
old_file = 'D:/PythonWorks/test.py'
new_file = 'D:/PythonWorks/test/bak.py'
shutil.copy(old_file, new_file) # 生成 'D:/PythonWorks/test/bak.py'
# 示例二: D:/PythonWorks/test 文件夹存在
import shutil
old_file = 'D:/PythonWorks/test.py'
new_path = 'D:/PythonWorks/test'
shutil.copy(old_file, new_path) # 生成 'D:/PythonWorks/test/test.py'
# 示例三: D:/PythonWorks/test 文件夹不存在
import shutil
old_file = 'D:/PythonWorks/test.py'
new_path = 'D:/PythonWorks/test'
shutil.copy(old_file, new_path) # 生成 'D:/PythonWorks/test' 无后缀文件# 方法二:linux系统
import os
os.system('cp -rf old_file new_file')复制文件夹
# 方法一:
# shutil.copytree(old_path, new_path) : 复制 old_path 的所有文件(包括子文件夹文件)至 new_path
# old_file: 待复制文件夹路径(如果 不存在,则报错)
# new_path: 目标文件夹路径(如果 已存在,则报错)
import shutil
old_path = 'D:/PythonWorks/test'
# bak 文件夹如果存在,则报错
new_path = 'D:/PythonWorks/bak'
shutil.copytree(old_path, new_path)# 方法二:linux系统
import os
os.system('cp -rf old_path new_path')
文件移动
移动文件
# shutil.move(old, new): 移动 文件
# old: 待移动文件路径(如果 不存在,则报错)
# new: 目标(文件路径 / 文件夹路径)
# 若 new 为 文件路径:
# 若 new 存在: 将 old 文件 移动为 new 文件(相当于重命名)
# 若 new 不存在: 则报错
# 若 new 为 文件夹路径:
# 若 new 存在: 将 old 文件 移动到 new 文件夹内
# 若 new 不存在: 会将文件夹 视为 无后缀的文件,进行文件移动
# 示例一:
import shutil
old_file = 'D:/PythonWorks/test.py'
new_file = 'D:/PythonWorks/test/bak.py'
shutil.move(old_file, new_file) # 生成 'D:/PythonWorks/test/bak.py'
# 示例二: D:/PythonWorks/test 文件夹存在
import shutil
old_file = 'D:/PythonWorks/test.py'
new_path = 'D:/PythonWorks/test'
shutil.move(old_file, new_path) # 移动到 'D:/PythonWorks/test/test.py'
# 示例三: D:/PythonWorks/test 文件夹不存在
import shutil
old_file = 'D:/PythonWorks/test.py'
new_path = 'D:/PythonWorks/test'
shutil.move(old_file, new_path) # 生成 'D:/PythonWorks/test' 无后缀文件移动文件夹
# shutil.move(old, new): 移动 文件夹
# old: 待移动文件夹路径(如果 不存在,则报错)
# new: 目标文件夹路径
# 若 new 存在: 将 old 文件夹 移动到 new 文件夹内
# 若 new 不存在: 创建 new 文件夹,然后将 old 文件夹所有文件 移动到 new 文件夹内(相当于对 old文件夹 重命名 为 new文件夹)
# 示例一: D:/PythonWorks/bak 文件夹存在
import shutil
old_path = 'D:/PythonWorks/test'
new_path = 'D:/PythonWorks/bak'
shutil.move(old_path, new_path) # test文件夹在 bak文件夹 内
# 示例二: D:/PythonWorks/test 文件夹不存在
import shutil
old_path = 'D:/PythonWorks/test'
new_path = 'D:/PythonWorks/bak'
shutil.move(old_path, new_path) # test文件夹里的所有文件 在 bak文件夹 内(相当于对 test文件夹 重命名 为 bak文件夹)
文件删除
删除文件
# 删除 单个文件
# 方法一:os.remove()
import os
file_1 = '/home/test/test_1.txt'
os.remove(file_1)
# 方法二:os.unlink()
import os
file_2 = '/home/test/test_2.txt'
os.unlink(file_2)删除空文件夹
# 删除 空文件夹(若文件夹非空则报错)
# 方法一:os.removedirs()
import os
folder_path_1 = '/home/test_1'
os.removedirs(folder_path_1)
# 方法二:os.rmdir()
import os
folder_path_2 = '/home/test_2'
os.rmdir(folder_path_2)删除文件夹
# -*- coding: utf-8 -*-
# 删除 文件夹(含子文件夹)
import os
def remove_dir(check_dir):
"""
# 功能:删除 check_dir 路径
# 如果 check_dir 为 文件,则删除 该文件
# 如果 check_dir 为 文件夹,则删除 该文件夹(含子文件夹)
# 输入:
# check_dir: 待删除的目标路径
"""
# 首先去除尾部 / 或 \ 符号
check_dir = check_dir.rstrip('/\\')
# 如果 check_dir 为 文件
if os.path.isfile(check_dir):
os.remove(check_dir)
print("[INFO] 删除文件:{}".format(check_dir))
# 如果 check_dir 为 文件夹
elif os.path.isdir(check_dir):
# 获取当前文件列表(包含子文件夹)
cur_dir_list = os.listdir(check_dir)
# 如果文件列表不为空,则遍历删除
if cur_dir_list:
for cur_dir in cur_dir_list:
# 拼接路径
cur_path = os.path.join(check_dir, cur_dir)
# 如果 cur_path 是 文件,则删除该文件
if os.path.isfile(cur_path):
os.remove(cur_path)
print("[INFO] 删除文件:{}".format(cur_path))
# 如果 cur_path 为 文件夹,则递归
elif os.path.isdir(cur_path):
remove_dir(cur_path)
# ---- 递归结束后会接着执行以下代码 ----
if os.path.exists(check_dir):
os.rmdir(check_dir)
print("[INFO] 删除文件夹:{}".format(check_dir))
# 如果文件列表为空,则直接删除此空的根文件夹
else:
os.rmdir(check_dir)
print("[INFO] 删除文件夹:{}".format(check_dir))
# 函数测试
check_dir = 'D:/FaramitaWorks/PythonWorks/test'
remove_dir(check_dir)
# 检验是否删除成功
if not (os.path.exists(check_dir)):
print("\n[SUCCESS] 删除成功:{}".format(check_dir))
else:
print("\n[ERROR] 删除失败:{}".format(check_dir))清空文件夹(保留指定文件)
# -*- coding: utf-8 -*-
# 清空指定文件夹及其子文件,但保留 target_list 中的所有文件
import os
def delete_files_not_in_target(target_path, target_files):
"""
# 功能:清空指定文件夹及其子文件,但保留 target_list 中的所有文件
# 输入:
# target_path: {str} 指定目录
# target_files: {list} 指定文件列表(仅文件名,不带路径)
"""
# 遍历目录
for root, dirs, files in os.walk(target_path):
# 遍历文件
for file in files:
# 如果文件不在目标文件列表中
if file not in target_files:
file_path = os.path.join(root, file)
# 删除文件
os.remove(file_path)
print( "[INFO] 已删除文件:{}".format(file_path) )
# 再次遍历目录,检查并删除空目录
for root, dirs, files in os.walk(target_path, topdown=False):
if not dirs and not files:
os.rmdir(root)
print( "[INFO] 已删除文件夹:{}".format(root) )
# 函数测试
target_path = "/home/faramita/test"
target_files = ["my_test.py", "one.txt"]
delete_files_not_in_target(target_path, target_files)
文件创建
新建文件夹
# -*- coding: utf-8 -*-
# 新建文件夹
import os
import sys
def new_folder(folder_path):
"""
# 功能:新建文件夹
# 输入:
# folder_path: 待创建的文件夹路径
"""
# 首先去除尾部 / 或 \ 符号
folder_path = folder_path.rstrip('/\\')
# 如果路径存在
if os.path.exists(folder_path):
print("[ERROR] 路径已存在:{}".format(folder_path))
# 退出程序
sys.exit()
# 如果不是文件夹路径格式
elif '.' in folder_path:
print("[ERROR] 文件夹 路径错误:{}".format(folder_path))
# 退出程序
sys.exit()
else:
os.makedirs(folder_path)
print("[INFO] 已新建文件夹:{}".format(folder_path))
# 函数测试
check_dir = 'D:/FaramitaWorks/PythonWorks/test'
new_folder(check_dir)文件保存准备
# -*- coding: utf-8 -*-
# 文件保存准备(为文件夹和文件添加 时间戳+uuid4 等)
def file_save_prepare(output_path, name_pre, file_type):
"""
# 功能:文件保存准备(为文件夹和文件添加 时间戳+uuid4 等)
# 输入:
# output_path: {str} 文件保存文件夹
# name_pre: {str} 文件名前缀
# file_type: {str} 文件类型,即文件后缀名,如["txt","png","mp3"]
# 输出:
# code, msg: {str} 状态码和对应信息说明
# abs_output_audio: {str} 文件保存的绝对路径
# 如:/home/faramita/20240706/name_pre-20240706142530-shdyekshyehfcgsd.file_type
"""
try:
# 设置文件输出路径,使用 时间戳+uuid4
timestamp = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
cur_date = timestamp[:8]
cur_time_floder = output_path + "/" + cur_date
# 如果日期文件夹不存在,则新建日期文件夹
if not (os.path.exists(cur_time_floder)):
os.makedirs(cur_time_floder)
uuid_str = uuid.uuid4().hex
output_file_name = name_pre + "-" + timestamp + "-" + uuid_str + "." + file_type.lower()
output_file = cur_time_floder + "/" + output_file_name
abs_output_file = os.path.abspath(output_file)
mylogger.info( "已完成文件保存准备:{}".format(abs_output_file) )
code = "200"
msg = "成功"
except Exception as err:
mylogger.error( "文件保存准备错误:{}".format(err) )
code = "302"
msg = "文件写入错误"
abs_output_file = ""
finally:
return code, msg, abs_output_file
# 函数测试
output_path= "/home/faramita/output"
name_pre= "audio_generate-慕夕"
file_type = "wav"
save_code, save_msg, abs_audio_file = file_save_prepare(output_path, name_pre, file_type)
文件读写
任意类型文件
# -*- coding: utf-8 -*-
# 文件读取
import os
import sys
def read_every_file(every_file):
"""
# 功能:读取 任何类型的 文件内容
# 输入:
# every_file: 待读取文件路径
# 输出:
# file_bytes: 文件内容(二进制bytes序列)
"""
try:
# 二进制读取文件
# (不推荐)使用 f = open(),使用后需要 close()
# (推荐)使用 with open() 创建运行时环境,执行完后自动退出,无需 close()
with open(every_file, 'rb') as f:
file_bytes = f.read()
# 文件读入异常保护
except FileNotFoundError:
print( "[ERROR] 文件不存在:{}".format(every_file) )
# 退出程序
sys.exit()
else:
print( "[INFO] 已读取文件:{}".format(every_file) )
return file_bytes# -*- coding: utf-8 -*-
# 文件写入
import os
import sys
def write_every_file(file_bytes, every_file, del_file='no'):
"""
# 功能:将 file_bytes 写入 every_file 文件
# 输入:
# file_bytes: 待写入内容(二进制bytes序列)
# every_file: 待保存文件路径
# del_file: 如写入前文件已存在,是否强制删除
# 可选:'yes',强制删除
# 'no'(默认),询问用户是否删除
"""
# 参数校验
if (del_file != 'yes') and (del_file != 'no'):
print( "[ERROR] del_file 错误:当前只支持 yes 或 no" )
# 退出程序
sys.exit()
# 先判断 every_file 是否存在
# 如果不存在,则直接生成新文件
if not os.path.isfile(every_file):
# 以 二进制方式 写入文件,依然推荐 with open()
with open(every_file, 'wb') as f:
f.write(file_bytes)
print( "[INFO] 已生成新文件:{}".format(every_file) )
else:
# 如果强制删除旧文件
if del_file == 'yes':
# 先删除
os.remove(every_file)
# 以 二进制方式 写入文件,依然推荐 with open()
with open(every_file, 'wb') as f:
f.write(file_bytes)
print( "[INFO] 旧文件已删除,已生成新文件:{}".format(every_file) )
else:
print("[WARNING] 文件已存在!是否用新文件覆盖旧文件?请输入 'yes' or 'no'.")
msg = "(input yes or no) >> "
delete_or_not = input(msg)
if delete_or_not == 'yes' or delete_or_not == 'y':
# 先删除
os.remove(every_file)
# 以 二进制方式 写入文件,依然推荐 with open()
with open(every_file, 'wb') as f:
f.write(file_bytes)
print( "[INFO] 旧文件已删除,已生成新文件:{}".format(every_file) )
else:
print( "[INFO] 未生成新文件,旧文件已保留:{}".format(every_file) )# 函数测试
old_file = "D:/FaramitaWorks/PythonWorks/test/test_old.jpg"
new_file = "D:/FaramitaWorks/PythonWorks/test/test_new.jpg"
file_bytes = read_every_file(old_file)
write_every_file(file_bytes, new_file)文本文件(txt / log)
# -*- coding: utf-8 -*-
# 文件读取
import os
import sys
def read_file_txt(txt_file, encode_type='utf-8'):
"""
# 功能:读取 txt_file 文件内容
# 输入:
# txt_file: 待读取文件路径
# encode_type: 文件编码方式
# 可选:'utf-8'(默认),最常用,包含中文字符
# 'gb18030',编码范围更广,包含少数民族字符
# 输出:
# file_lines: 文件内容,按行存为list
"""
# 参数校验
if (encode_type != 'utf-8') and (encode_type != 'gb18030'):
print( "[ERROR] encode_type 错误:当前只支持 utf-8 或 gb18030" )
# 退出程序
sys.exit()
try:
# 读取文件
# (不推荐)使用 f = open(),使用后需要 close()
# (推荐)使用 with open() 创建运行时环境,执行完后自动退出,无需 close()
with open(txt_file, encoding=encode_type, errors='ignore') as f:
# 1. 每次一行,读取文件,不会直接保存读取内容:
file_lines = []
for line in f:
# 文件 原内容 保存
file_lines.append(line)
# 文件 原内容选择性 保存
# file_lines.append(line.split(':')[1])
# 2. 若要直接保存读取内容:
# 小文件,使用 f.read() 一次性读取完
# file_content = f.read()
# 大文件,使用 f.readline() 每次读取一行
# file_content = f.readline()
# 大文件,使用 f.readlines() 一次读取所有内容,并按行存为list(推荐)
# file_lines = f.readlines()
# 无法确定文件大小,反复调用 read(size) 决定一次读多少字符
# file_content_part = file.read(10)
# 文件读入异常保护
except FileNotFoundError:
print( "[ERROR] 文件不存在:{}".format(txt_file) )
# 退出程序
sys.exit()
else:
print( "[INFO] 已读取文件:{}".format(txt_file) )
return file_lines# -*- coding: utf-8 -*-
# 文件写入
import os
import sys
def write_file_txt(file_lines, txt_file, write_type='w', del_file='no'):
"""
# 功能:将 file_lines列表 内容按行写入 txt_file 文件(txt/log)
# 输入:
# file_lines: 待写入内容(列表)
# txt_file: 待保存文件路径
# write_type: 文件写入方式
# 可选:'w'(默认),清空写入(会先初始化清空文件)
# 'a',追加写入(不会初始化清空文件,只在文件末尾追加)
# del_file: 如写入前文件已存在,是否强制删除
# 可选:'yes',强制删除
# 'no'(默认),询问用户是否删除
"""
# 参数校验
if (not txt_file.endswith('.txt')) and (not txt_file.endswith('.log')):
print( "[ERROR] txt_file 错误:当前只支持保存 .txt 或 .log 文件" )
# 退出程序
sys.exit()
if (write_type != 'w') and (write_type != 'a'):
print( "[ERROR] write_type 错误:当前只支持 w 或 a" )
# 退出程序
sys.exit()
if (del_file != 'yes') and (del_file != 'no'):
print( "[ERROR] del_file 错误:当前只支持 yes 或 no" )
# 退出程序
sys.exit()
# 先判断 txt_file 是否存在
# 如果不存在,则直接生成新文件
if not os.path.isfile(txt_file):
# 写入文件,依然推荐 with open()
with open(txt_file, write_type, errors='ignore') as f:
# 按行写入
f.writelines(file_lines)
print( "[INFO] 已生成新文件:{}".format(txt_file) )
else:
# 如果强制删除旧文件
if del_file == 'yes':
# 先删除
os.remove(txt_file)
# 写入文件,依然推荐 with open()
with open(txt_file, write_type, errors='ignore') as f:
# 按行写入
f.writelines(file_lines)
print( "[INFO] 旧文件已删除,已生成新文件:{}".format(txt_file) )
else:
print("[WARNING] 文件已存在!是否用新文件覆盖旧文件?请输入 'yes' or 'no'.")
msg = "(input yes or no) >> "
delete_or_not = input(msg)
if delete_or_not == 'yes' or delete_or_not == 'y':
os.remove(txt_file)
# 写入文件,依然推荐 with open()
with open(txt_file, write_type, errors='ignore') as f:
# 按行写入
f.writelines(file_lines)
print( "[INFO] 旧文件已删除,已生成新文件:{}".format(txt_file) )
else:
print( "[INFO] 未生成新文件,旧文件已保留:{}".format(txt_file) )# 函数测试
old_txt_file = "D:/FaramitaWorks/PythonWorks/test/test_old.txt"
new_txt_file = "D:/FaramitaWorks/PythonWorks/test/test_new.txt"
file_lines = read_file_txt(old_txt_file)
write_file_txt(file_lines, new_txt_file)json 文件
json 文件读写
pickle 文件
pickle 文件读写
csv 文件
# -*- coding: utf-8 -*-
# 文件读取
import sys
import csv
def read_file_csv(csv_file, encode_type='utf-8'):
"""
# 功能:读取 csv_file 文件内容
# 输入:
# csv_file: 待读取文件路径
# encode_type: 文件编码方式
# 可选:'utf-8'(默认),最常用,包含中文字符
# 'gb18030',编码范围更广,包含少数民族字符
# 输出:
# file_content: 文件内容
"""
# 参数校验
if (encode_type != 'utf-8') and (encode_type != 'gb18030'):
print( "[ERROR] encode_type 错误:当前只支持 utf-8 或 gb18030" )
# 退出程序
sys.exit()
file_content = []
try:
# 读取文件
# (不推荐)使用 f = open(),使用后需要 close()
# (推荐)使用 with open() 创建运行时环境,执行完后自动退出,无需 close()
with open(csv_file, encoding=encode_type, errors='ignore') as f:
file_info = csv.reader(f)
# 保存读取内容
for file_i in file_info:
# 文件 原内容 保存
file_content.append(file_i)
# 文件 原内容选择性 保存
# file_content.append(file_i.split(':')[1])
# 文件读入异常保护
except FileNotFoundError:
print( "[ERROR] 文件不存在:{}".format(csv_file) )
# 退出程序
sys.exit()
else:
print( "[INFO] 已读取文件:{}".format(csv_file) )
return file_content# -*- coding: utf-8 -*-
# 文件写入
import os
import sys
import csv
def write_file_csv(file_content, csv_file, encode_type='utf-8-sig', write_type='w', del_file='no'):
"""
# 功能:将 file_content 内容写入 csv_file 文件(.csv)
# 输入:
# file_content: 待写入内容
# csv_file: 待保存文件路径
# encode_type: 文件编码方式
# 可选:'utf-8-sig'(默认),保证中文不会乱码
# write_type: 文件写入方式
# 可选:'w'(默认),清空写入(会先初始化清空文件)
# 'a',追加写入(不会初始化清空文件,只在文件末尾追加)
# del_file: 如写入前文件已存在,是否强制删除
# 可选:'yes',强制删除
# 'no'(默认),询问用户是否删除
"""
# 参数校验
if not csv_file.endswith('.csv'):
print( "[ERROR] csv_file 错误:当前只支持保存 .csv 文件" )
# 退出程序
sys.exit()
if (write_type != 'w') and (write_type != 'a'):
print( "[ERROR] write_type 错误:当前只支持 w 或 a" )
# 退出程序
sys.exit()
if (del_file != 'yes') and (del_file != 'no'):
print( "[ERROR] del_file 错误:当前只支持 yes 或 no" )
# 退出程序
sys.exit()
# 先判断 csv_file 是否存在
# 如果不存在,则直接生成新文件
if not os.path.isfile(csv_file):
# 存入csv
# newline='' 表示以空格作为换行符,保证不会出现新空白行
with open(csv_file, write_type, encoding=encode_type, newline='') as f:
csv_writer = csv.writer(f)
# 按行写入内容
for line_i in range(len(file_content)):
csv_writer.writerow(file_content[line_i])
print( "[INFO] 已生成新文件:{}".format(csv_file) )
else:
# 如果强制删除旧文件
if del_file == 'yes':
# 先删除
os.remove(csv_file)
# 存入csv
# newline='' 表示以空格作为换行符,保证不会出现新空白行
with open(csv_file, write_type, encoding=encode_type, newline='') as f:
csv_writer = csv.writer(f)
# 按行写入内容
for line_i in range(len(file_content)):
csv_writer.writerow(file_content[line_i])
print( "[INFO] 旧文件已删除,已生成新文件:{}".format(csv_file) )
else:
print("[WARNING] 文件已存在!是否用新文件覆盖旧文件?请输入 'yes' or 'no'.")
msg = "(input yes or no) >> "
delete_or_not = input(msg)
if delete_or_not == 'yes' or delete_or_not == 'y':
# 先删除
os.remove(csv_file)
# 存入csv
# newline='' 表示以空格作为换行符,保证不会出现新空白行
with open(csv_file, write_type, encoding=encode_type, newline='') as f:
csv_writer = csv.writer(f)
# 按行写入内容
for line_i in range(len(file_content)):
csv_writer.writerow(file_content[line_i])
print( "[INFO] 旧文件已删除,已生成新文件:{}".format(csv_file) )
else:
print( "[INFO] 未生成新文件,旧文件已保留:{}".format(csv_file) )# 函数测试
file_content = []
file_content.append(['姓名', '性别', '年龄'])
file_content.append(['juju', 'man', 20])
file_content.append(['fafa', 'man', 18])
csv_file = 'D:/FaramitaWorks/PythonWorks/test/test.csv'
write_file_csv(file_content, csv_file)
file_content_new = read_file_csv(csv_file)
print(file_content_new) # [['\ufeff姓名', '性别', '年龄'], ['juju', 'man', '20'], ...]excel 文件(xlsx)
# -*- coding: utf-8 -*-
# 文件读取
import sys
import openpyxl
def read_file_xlsx(xlsx_file, read_type='sheet_index', sheet_index=1, sheet_name=''):
"""
# 功能:读取 xlsx_file文件 内容
# 输入:
# xlsx_file: 待读取文件路径
# read_type: 读取方式
# 可选: 'all',所有sheet
# 'sheet_index'(默认),sheet下标,必须 >=1
# 'sheet_name',sheet名
# 输出:
# xlsx_data: 所有/指定 sheet表 内容
# sheets_name_list: 所有 sheet表 名
"""
# 参数校验
if (read_type != 'all') and (read_type != 'sheet_index') and (read_type != 'sheet_name'):
print( "[ERROR] read_type 错误:当前只支持 all 或 sheet_index 或 sheet_name" )
# 退出程序
sys.exit()
if int(sheet_index) < 1:
print( "[ERROR] sheet_index 错误:必须 >= 1" )
# 退出程序
sys.exit()
try:
# 打开 xlsx_file
wbook = openpyxl.load_workbook(xlsx_file)
# 获取 wbook 中所有 sheet 名称
sheets_name_list = wbook.sheetnames
# sheets_name_list = wbook.get_sheet_names()
# xlsx_data列表 用来保存所有数据
xlsx_data = []
if read_type == 'sheet_index':
# 先判断 sheet_index 是否合法
if int(sheet_index) > len(sheets_name_list):
print("[ERROR] 当前 sheet_index({}) > sheet总数({})".format(
int(sheet_index), len(sheets_name_list)))
# 退出程序
sys.exit()
print( "[INFO] 将读取 sheet({}) 的数据".format(int(sheet_index)) )
# 指定 sheet
sheet_name = sheets_name_list[int(sheet_index)-1]
wsheet = wbook[sheet_name]
# wsheet= wbook.get_sheet_by_name(sheet_name)
# 遍历 sheet数据
# 先将 sheet数据 存入内存变量,加速读取
# 注意 存入元组后,行列编号起始值 均为 0
sheet_data_temp = tuple(wsheet)
# sheet_data列表 用来保存 sheet数据
sheet_data = []
# 获取 最大行、最大列
m_row= wsheet.max_row
m_column= wsheet.max_column
# 按行 循环遍历
for row_i in range(m_row):
row_temp = []
for col_j in range(m_column):
row_temp.append(sheet_data_temp[row_i][col_j].value)
sheet_data.append(row_temp)
xlsx_data.append(sheet_data)
elif read_type == 'sheet_name':
# 先判断 sheet_name 是否合法
if str(sheet_name) not in sheets_name_list:
print( "[ERROR] 没有此 sheet_name :{}".format(str(sheet_name)) )
print( "[ERROR] 可选 sheet_name 为:" )
print( sheets_name_list )
# 退出程序
sys.exit()
print( "[INFO] 将读取 sheet({}) 的数据".format(str(sheet_name)) )
# 指定 sheet
wsheet = wbook[sheet_name]
# wsheet= wbook.get_sheet_by_name(sheet_name)
# 遍历 sheet数据
# 先将 sheet数据 存入内存变量,加速读取
# 注意 存入元组后,行列编号起始值 均为 0
sheet_data_temp = tuple(wsheet)
# sheet_data列表 用来保存 sheet数据
sheet_data = []
# 获取 最大行、最大列
m_row = wsheet.max_row
m_column = wsheet.max_column
# 按行 循环遍历
for row_i in range(m_row):
row_temp = []
for col_j in range(m_column):
row_temp.append(sheet_data_temp[row_i][col_j].value)
sheet_data.append(row_temp)
xlsx_data.append(sheet_data)
else:
print( "[INFO] 将读取 所有sheet 的数据" )
# 循环每个sheet
for s_name in sheets_name_list:
# 指定 sheet
wsheet = wbook[s_name]
# wsheet= wbook.get_sheet_by_name(s_name)
# 遍历 sheet数据
# 先将 sheet数据 存入内存变量,加速读取
# 注意 存入元组后,行列编号起始值 均为 0
sheet_data_temp = tuple(wsheet)
# sheet_data列表 用来保存 sheet数据
sheet_data = []
# 获取 最大行、最大列
m_row= wsheet.max_row
m_column= wsheet.max_column
# 按行 循环遍历
for row_i in range(m_row):
row_temp = []
for col_j in range(m_column):
row_temp.append(sheet_data_temp[row_i][col_j].value)
sheet_data.append(row_temp)
xlsx_data.append(sheet_data)
# 文件读入异常保护
except FileNotFoundError:
print( "[ERROR] 文件不存在:{}".format(xlsx_file) )
# 退出程序
sys.exit()
else:
print( "[INFO] 已读取文件:{}".format(xlsx_file) )
return xlsx_data, sheets_name_list# -*- coding: utf-8 -*-
# 文件新建
import os
import sys
import openpyxl
def write_file_xlsx(xlsx_file, xlsx_data, sheets_name_list=['sheet1'], del_file='no'):
"""
# 功能:将 xlsx_data 内容写入 xlsx_file 文件(.xlsx/.xlsm)
# 输入:
# xlsx_file: 待保存文件路径
# xlsx_data: 待写入内容,列表,其内元素 为 sheet内容
# sheets_name_list: 所有 sheet 表,列表
# del_file: 如写入前文件已存在,是否强制删除
# 可选:'yes',强制删除
# 'no'(默认),询问用户是否删除
"""
# 参数校验
if (not xlsx_file.endswith('.xlsx')) and (not xlsx_file.endswith('.xlsm')):
print( "[ERROR] xlsx_file 错误:当前只支持保存 .xlsx/.xlsm 文件" )
# 退出程序
sys.exit()
if not sheets_name_list:
print( "[ERROR] sheets_name_list 错误:至少要有 1 个 sheet 表名" )
# 退出程序
sys.exit()
if ('' in sheets_name_list) or (' ' in sheets_name_list):
print( "[ERROR] sheets_name_list 错误:sheet 表名不能为 空 或 空格" )
# 退出程序
sys.exit()
if (del_file != 'yes') and (del_file != 'no'):
print( "[ERROR] del_file 错误:当前只支持 yes 或 no" )
# 退出程序
sys.exit()
# 先判断 xlsx_file 是否存在
# 如果不存在,则直接生成新文件
if not os.path.isfile(xlsx_file):
# 存入 xlsx_file
# 新建 excel 工作簿 (Workbook)
wbook = openpyxl.Workbook()
# 对每个sheet表写入内容
for sheet_i in range(len(sheets_name_list)):
# 在索引 sheet_i 处新增sheet:sheets_name_list[sheet_i]
wsheet = wbook.create_sheet(sheets_name_list[sheet_i], sheet_i)
# xlsx_data[sheet_i] 为 sheet_i 的数据
# len(xlsx_data[sheet_i]) 为 sheet_i 的行数
# len(xlsx_data[sheet_i][0]) 为 sheet_i 的列数
for row_i in range(len(xlsx_data[sheet_i])):
for col_i in range(len(xlsx_data[sheet_i][0])):
# cell(i, j)代表 sheet表 的 第i行j列 单元格
# 注意 行列编号起始值 均为 1
wsheet.cell(row_i+1, col_i+1).value = xlsx_data[sheet_i][row_i][col_i]
# 删除新建 Workbook 时自带的 sheet
del wbook['Sheet']
# wbook.remove('Sheet')
# 保存 excel 文件
wbook.save(xlsx_file)
print( "[INFO] 已生成新文件:{}".format(xlsx_file) )
else:
# 如果强制删除旧文件
if del_file == 'yes':
# 先删除
os.remove(xlsx_file)
# 存入 xlsx_file
# 新建 excel 工作簿 (Workbook)
wbook = openpyxl.Workbook()
# 对每个sheet表写入内容
for sheet_i in range(len(sheets_name_list)):
# 在索引 sheet_i 处新增sheet:sheets_name_list[sheet_i]
wsheet = wbook.create_sheet(sheets_name_list[sheet_i], sheet_i)
# xlsx_data[sheet_i] 为 sheet_i 的数据
# len(xlsx_data[sheet_i]) 为 sheet_i 的行数
# len(xlsx_data[sheet_i][0]) 为 sheet_i 的列数
for row_i in range(len(xlsx_data[sheet_i])):
for col_i in range(len(xlsx_data[sheet_i][0])):
# cell(i, j)代表 sheet表 的 第i行j列 单元格
# 注意 行列编号起始值 均为 1
wsheet.cell(row_i+1, col_i+1).value = xlsx_data[sheet_i][row_i][col_i]
# 删除新建 Workbook 时自带的 sheet
del wbook['Sheet']
# wbook.remove('Sheet')
# 保存 excel 文件
wbook.save(xlsx_file)
print( "[INFO] 旧文件已删除,已生成新文件:{}".format(xlsx_file) )
else:
print("[WARNING] 文件已存在!是否用新文件覆盖旧文件?请输入 'yes' or 'no'.")
msg = "(input yes or no) >> "
delete_or_not = input(msg)
if delete_or_not == 'yes' or delete_or_not == 'y':
# 先删除
os.remove(xlsx_file)
# 存入 xlsx_file
# 新建 excel 工作簿 (Workbook)
wbook = openpyxl.Workbook()
# 对每个sheet表写入内容
for sheet_i in range(len(sheets_name_list)):
# 在索引 sheet_i 处新增sheet:sheets_name_list[sheet_i]
wsheet = wbook.create_sheet(sheets_name_list[sheet_i], sheet_i)
# xlsx_data[sheet_i] 为 sheet_i 的数据
# len(xlsx_data[sheet_i]) 为 sheet_i 的行数
# len(xlsx_data[sheet_i][0]) 为 sheet_i 的列数
for row_i in range(len(xlsx_data[sheet_i])):
for col_i in range(len(xlsx_data[sheet_i][0])):
# cell(i, j)代表 sheet表 的 第i行j列 单元格
# 注意 行列编号起始值 均为 1
wsheet.cell(row_i+1, col_i+1).value = xlsx_data[sheet_i][row_i][col_i]
# 删除新建 Workbook 时自带的 sheet
del wbook['Sheet']
# wbook.remove('Sheet')
# 保存 excel 文件
wbook.save(xlsx_file)
print( "[INFO] 旧文件已删除,已生成新文件:{}".format(xlsx_file) )
else:
print( "[INFO] 未生成新文件,旧文件已保留:{}".format(xlsx_file) )# -*- coding: utf-8 -*-
# 文件改动
import sys
import openpyxl
from openpyxl import styles
def change_file_xlsx(xlsx_file, read_type='sheet_index', sheet_index=1, sheet_name=''):
"""
# 功能:改动 xlsx_file文件 内容
# 输入:
# xlsx_file: 待改动文件路径
# read_type: 读取方式
# 可选: 'all',所有sheet
# 'sheet_index'(默认),sheet下标,必须 >=1
# 'sheet_name',sheet名
# 输出:
# xlsx_data: 所有/指定 sheet表 内容
# sheets_name_list: 所有 sheet表 名
"""
# 参数校验
if (read_type != 'all') and (read_type != 'sheet_index') and (read_type != 'sheet_name'):
print( "[ERROR] read_type 错误:当前只支持 all 或 sheet_index 或 sheet_name" )
# 退出程序
sys.exit()
if int(sheet_index) < 1:
print( "[ERROR] sheet_index 错误:必须 >= 1" )
# 退出程序
sys.exit()
try:
# 先保存 RGB颜色 字典
color_dic = {
'black': '000000',
'white': 'FFFFFF',
'red': 'FF0000',
'green': '00FF00',
'blue': '0000FF',
'yellow': 'FFFF00',
'orange': 'FFB90F',
'light_blue': '1E90FF',
'light_green': '9ACD32'}
# 打开 xlsx_file
wbook = openpyxl.load_workbook(xlsx_file)
# 获取 wbook 中所有 sheet 名称
sheets_name_list = wbook.sheetnames
# sheets_name_list = wbook.get_sheet_names()
if read_type == 'sheet_index':
# 先判断 sheet_index 是否合法
if int(sheet_index) > len(sheets_name_list):
print("[ERROR] 当前 sheet_index({}) > sheet总数({})".format(
int(sheet_index), len(sheets_name_list)))
# 退出程序
sys.exit()
print( "[INFO] 将改动 sheet({}) 的数据".format(int(sheet_index)) )
# 指定 sheet
sheet_name = sheets_name_list[int(sheet_index)-1]
wsheet = wbook[sheet_name]
# wsheet= wbook.get_sheet_by_name(sheet_name)
# 修改 指定单元格 的值(如单元格 2, 1)
# 注意 行列编号起始值 均为 1
wsheet.cell(2, 1).value = 'guagua'
# 获取 最大行、最大列
m_row= wsheet.max_row
m_column= wsheet.max_column
# 标题行(第1行)格式设置
for col_i in range(m_column):
# 设置字体(如:微软雅黑-12号-加粗-斜体-无删除线-红色)
cur_font = styles.Font(name='微软雅黑', size=12, bold=True, italic=True, strike=False, color=color_dic['red'])
wsheet.cell(1, col_i+1).font = cur_font
# 设置内容布局(垂直居中 + 水平居中)
wsheet.cell(1, col_i+1).alignment = styles.Alignment(horizontal='center', vertical='center')
# 设置背景色
cur_fill = styles.PatternFill(fill_type='solid', fgColor=color_dic['yellow'])
wsheet.cell(1, col_i+1).fill = cur_fill
# 行高
wsheet.row_dimensions[1].height = 18
# 列宽
wsheet.column_dimensions['A'].width = 12
# 合并单元格,往左上角写入数据即可(如A1)
# wsheet.merge_cells('A1:C3')
# 取消合并单元格
# wsheet.unmerge_cells('A1:C3')
elif read_type == 'sheet_name':
# 先判断 sheet_name 是否合法
if str(sheet_name) not in sheets_name_list:
print( "[ERROR] 没有此 sheet_name :{}".format(str(sheet_name)) )
print( "[ERROR] 可选 sheet_name 为:" )
print( sheets_name_list )
# 退出程序
sys.exit()
print( "[INFO] 将改动 sheet({}) 的数据".format(str(sheet_name)) )
# 指定 sheet
wsheet = wbook[sheet_name]
# wsheet= wbook.get_sheet_by_name(sheet_name)
# 修改 指定单元格 的值(如单元格 2, 1)
# 注意 行列编号起始值 均为 1
wsheet.cell(2, 1).value = 'guagua'
# 获取 最大行、最大列
m_row= wsheet.max_row
m_column= wsheet.max_column
# 标题行(第1行)格式设置
for col_i in range(m_column):
# 设置字体(如:微软雅黑-12号-加粗-斜体-无删除线-红色)
cur_font = styles.Font(name='微软雅黑', size=12, bold=True, italic=True, strike=False, color=color_dic['red'])
wsheet.cell(1, col_i+1).font = cur_font
# 设置内容布局(垂直居中 + 水平居中)
wsheet.cell(1, col_i+1).alignment = styles.Alignment(horizontal='center', vertical='center')
# 设置背景色
cur_fill = styles.PatternFill(fill_type='solid', fgColor=color_dic['yellow'])
wsheet.cell(1, col_i+1).fill = cur_fill
# 行高
wsheet.row_dimensions[1].height = 18
# 列宽
wsheet.column_dimensions['A'].width = 12
# 合并单元格,往左上角写入数据即可(如A1)
# wsheet.merge_cells('A1:C3')
# 取消合并单元格
# wsheet.unmerge_cells('A1:C3')
else:
print( "[INFO] 将改动 所有sheet 的数据" )
# 循环每个sheet
for s_name in sheets_name_list:
# 指定 sheet
wsheet = wbook[s_name]
# wsheet= wbook.get_sheet_by_name(s_name)
# 修改 指定单元格 的值(如单元格 2, 1)
# 注意 行列编号起始值 均为 1
wsheet.cell(2, 1).value = 'guagua'
# 获取 最大行、最大列
m_row= wsheet.max_row
m_column= wsheet.max_column
# 标题行(第1行)格式设置
for col_i in range(m_column):
# 设置字体(如:微软雅黑-12号-加粗-斜体-无删除线-红色)
cur_font = styles.Font(name='微软雅黑', size=12, bold=True, italic=True, strike=False, color=color_dic['red'])
wsheet.cell(1, col_i+1).font = cur_font
# 设置内容布局(垂直居中 + 水平居中)
wsheet.cell(1, col_i+1).alignment = styles.Alignment(horizontal='center', vertical='center')
# 设置背景色
cur_fill = styles.PatternFill(fill_type='solid', fgColor=color_dic['yellow'])
wsheet.cell(1, col_i+1).fill = cur_fill
# 行高
wsheet.row_dimensions[1].height = 18
# 列宽
wsheet.column_dimensions['A'].width = 12
# 合并单元格,往左上角写入数据即可(如A1)
# wsheet.merge_cells('A1:C3')
# 取消合并单元格
# wsheet.unmerge_cells('A1:C3')
# 文件读入异常保护
except FileNotFoundError:
print( "[ERROR] 文件不存在:{}".format(xlsx_file) )
# 退出程序
sys.exit()
else:
wbook.save(xlsx_file)
print( "[INFO] 已保存改动:{}".format(xlsx_file) )# 函数测试
old_xlsx_file = 'D:/FaramitaWorks/PythonWorks/test/test.xlsx'
new_xlsx_file = 'D:/FaramitaWorks/PythonWorks/test/test_new.xlsx'
xlsx_data, sheets_name_list = read_file_xlsx(old_xlsx_file, read_type='all')
write_file_xlsx(new_xlsx_file, xlsx_data, sheets_name_list)
change_file_xlsx(new_xlsx_file)
数据库 - SQLite
连接数据库
import sqlite3
# 连接现有数据库
# 如果该数据库不存在,将会新建同名数据库
# 最终返回数据库对象
db_file = "/home/test/db_test.db"
conn = sqlite3.connect(db_file, isolation_level=None, timeout=300)
# isolation_level 为事务隔离级别,设为None即自动提交,即每次写数据库都提交
# 若无isolation_level参数,则不会自动提交,应通过conn.commit()提交事务
# timeout参数表示当数据库被多个连接访问,且其中一个修改了数据库,此时数据库将被锁定,直到事务提交
# timeout=300表示连接等待锁定的持续时间,直到发生异常断开连接,默认为5.0(5秒)
print( "[INFO] 已连接数据库:{}".format(db_file) )
创建表
import sqlite3
db_file = "/home/test/db_test.db"
conn = sqlite3.connect(db_file)
print( "[INFO] 已连接数据库:{}".format(db_file) )
cu = conn.cursor()
cu.execute('''CREATE TABLE Student
(ID INT NOT NULL,
Name TEXT NOT NULL,
Age INT NOT NULL,
Score REAL,
PRIMARY KEY (ID,Name)
);''')
conn.commit()
print( "[INFO] 已新建表:Student" )
conn.close()
# cu.execute(sql_code):sql_code即为SQL语句,该函数接收任何SQL语句,并执行得到结果
# cu.execute('''CREATE TABLE Student (**); ''') :创建表Student,(**)为表的具体结构,;代表结束
# ID INT NOT NULL:ID列,INT(整数型),NOT NULL(不能为空)
# Name TEXT NOT NULL:Name列,TEXT(字符串型),NOT NULL(不能为空)
# Age INT NOT NULL:Age列,INT(整数型),NOT NULL(不能为空)
# Score REAL:Score列,REAL(浮点数型)
# PRIMARY KEY (ID,Name):表示主键为ID+Name
插入数据(INSERT)
import sqlite3
db_file = "/home/test/db_test.db"
conn = sqlite3.connect(db_file)
print( "[INFO] 已连接数据库:{}".format(db_file) )
cu = conn.cursor()
# 依次插入数据行
column_name = "ID, Name, Age, Score"
ID = [1, 2, 3]
Name = ["juju", "fafa", "kaka"]
Age = [18, 17, 16]
Max_Score = [98.5, 73.5, 61.0]
for i in range(len(ID)):
SQL_code = "INSERT INTO Student ({}) VALUES ('{}', '{}', '{}', '{}')".format(
column_name, ID[i], Name[i], Age[i], Max_Score[i])
cu.execute(SQL_code)
conn.commit()
print( "[INFO] 已插入数据" )
conn.close()
查询数据(SELECT)
import sqlite3
db_file = "/home/test/db_test.db"
conn = sqlite3.connect(db_file)
print( "[INFO] 已连接数据库:{}".format(db_file) )
cu = conn.cursor()
# 遍历指定列
#column_name = "Name, Score"
#value_rows = cu.execute("SELECT " + column_name + " from Student")
# 遍历所有列
value_rows = cu.execute("SELECT * from Student")
DB_Student_data = []
for row in value_rows:
print(row)
print(row[1])
DB_Student_data.append(row)
print( "[INFO] 已查询数据" )
conn.close()
更新数据(UPDATE)
import sqlite3
db_file = "/home/test/db_test.db"
conn = sqlite3.connect(db_file)
print( "[INFO] 已连接数据库:{}".format(db_file) )
cu = conn.cursor()
cu.execute("UPDATE Student set Score=93.6 where ID=1;")
conn.commit()
print( "[INFO] 已更新 {} 行数据".format(conn.total_changes) )
conn.close()
删除数据(DELETE)
import sqlite3
db_file = "/home/test/db_test.db"
conn = sqlite3.connect(db_file)
print( "[INFO] 已连接数据库:{}".format(db_file) )
cu = conn.cursor()
cu.execute("DELETE from Student where ID=2;")
conn.commit()
print( "[INFO] 已删除 {} 行数据".format(conn.total_changes) )
conn.close()
评论区