侧边栏壁纸
博主头像
晨的博客 博主等级

来去如一,真性湛然。风收云散,月在青天。

  • 累计撰写 14 篇文章
  • 累计创建 14 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

Python 基础

野生数分狮 - 晨
2024-03-16 / 0 评论 / 2 点赞 / 20 阅读 / 0 字

逻辑控制

条件语句

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 zero

raise 语句

# 基本语法格式
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()

  ‍

  ‍

2
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin

评论区