函数&模块
1.函数
1.函数入门
1.1初识函数
-
函数,可以当做一大堆功能代码的集合
''' 函数格式 def 函数名():函数内执行的业务代码函数名() '''def info():print("输出第一行数据")print("输出第二行数据")print("输出第三行数据")info()
输出第一行数据 输出第二行数据 输出第三行数据
-
函数在项目开发中用到的两种应用场景
-
有重复代码,用函数增加代码的重用性
# 重复代码 def send_message():# 执行业务passcpuview = 0.0 memoryview = 0.0 diskview = 00.0 print("欢迎使用计算机监控系统".center(20, "*")) if cpuview > 90 / 100:send_message() if memoryview > 98 / 100:send_message() if diskview > 99 / 100:send_message()
-
代码太长,用函数增强代码的可读性
# 代码太长 def calculate_same_num_rule():passdef calculate_same_color_rule():passdef calculate_straight_rule():passdef calculate_double_card_rule():passdef calculate_single_card_rule():pass
-
1.2函数的参数
1.参数
-
在定义函数时,如果括号中添加变量,称为它函数的形式参数
# 定义函数 def func(a1, a2, a3):print(a1+a2+a3) # 4# 执行函数并传入参数 func(1, 2,1)
-
位置传参
''' 执行函数时,传入参数一一对应函数的形参 ''' # 位置传参 def add(a1, a2):print(a1 + a2) # 3# 执行函数 add(1, 2)
-
关键字传参
# 关键字传参 def adds(n1, n2):print(n1 + n2) # 5adds(n1=1, n2=4)
2.默认参数
# 默认参数
def add_default(a1, a2, a3=15):print(a1 + a2 + a3)# 位置传参-有默认参数的函数,可以忽略默认参数,不传实参
add_default(1, 2) # 18
add_default(1, 2, 3) # 6# 关键字传参- 位置和关键字混合搭配时,关键字传参要放在后面
add_default(1, 2, a3=12) # 15
3.动态参数
"""
注意点:- **必须放在*后面- 参数和动态参数混合使用时,动态参数只能放在后面- 默认值参数和动态参数同时存在,默认值参数放在动态参数前
"""def add_other_Args(a1, a2, a3=15, *args, num=10, **kwargs):print(a1, a2, a3, num, args, kwargs)# 默认值参数 num,在实际应用中,并不能修改其值,默认值参数放在动态参数前面
add_other_Args(12, 56, 89, 12, 45, 56, 78, name="Terry", email="hjf***@gmail.com")
1.3函数返回值
-
开发过程中,函数可以解决一些实际业务,某些业务的功能实现之后需要反馈结果,因此函数有了返回值的概念
def xml_to_list(city):data_list = []url = "http://ws.webxml.com.cn//WebServices/WeatherWebService.asmx/getWeatherbyCityName?theCityName={}".format(city)res = requests.get(url=url)'''<?xml version="1.0" encoding="utf-8"?><ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://WebXml.com.cn/"><string>直辖市</string><string>北京</string><string>54511</string><string>54511.jpg</string><string>2024/3/8 9:44:19</string><string>-2℃/11℃</string><string>3月8日 晴</string><string>西南风小于3级</string><string>0.gif</string><string>0.gif</string><string>今日天气实况:气温:5.5℃;风向/风力:南风 2级;湿度:24%;紫外线强度:强。</string><string>感冒指数:极易发,天气寒冷,昼夜温差极大。运动指数:较不宜,天气寒冷,推荐您进行室内运动。过敏指数:较易发,外出需远离过敏源,适当采取防护措施。穿衣指数:寒冷,建议着厚羽绒服等隆冬服装。洗车指数:适宜,天气较好,适合擦洗汽车。紫外线指数:强,涂擦SPF大于15、PA+防晒护肤品。</string><string>-2℃/13℃</string><string>3月9日 晴</string><string>西风转北风小于3级</string><string>0.gif</string><string>0.gif</string><string>0℃/13℃</string><string>3月10日 晴转多云</string><string>西北风转北风小于3级</string><string>0.gif</string><string>1.gif</string><string>北京位于华北平原西北边缘,市中心位于北纬39度,东经116度,四周被河北省围着,东南和天津市相接。全市面积一万六千多平方公里,辖12区6县,人口1100余万。北京为暖温带半湿润大陆性季风气候,夏季炎热多雨,冬季寒冷干燥,春、秋短促,年平均气温10-12摄氏度。北京是世界历史文化名城和古都之一。早在七十万年前,北京周口店地区就出现了原始人群部落“北京人”。而北京建城也已有两千多年的历史,最初见于记载的名字为“蓟”。公元前1045年北京成为蓟、燕等诸侯国的都城;公元前221年秦始皇统一中国以来,北京一直是中国北方重镇和地方中心;自公元938年以来,北京又先后成为辽陪都、金上都、元大都、明清国都。1949年10月1日正式定为中华人民共和国首都。北京具有丰富的旅游资源,对外开放的旅游景点达200多处,有世界上最大的皇宫紫禁城、祭天神庙天坛、皇家花园北海、皇家园林颐和园,还有八达岭、慕田峪、司马台长城以及世界上最大的四合院恭王府等各胜古迹。全市共有文物古迹7309项,其中国家文物保护单位42个,市级文物保护单位222个。北京的市树为国槐和侧柏,市花为月季和菊花。另外,北京出产的象牙雕刻、玉器雕刻、景泰蓝、地毯等传统手工艺品驰誉世界。</string></ArrayOfString>'''print(res.text)root = ET.XML(res.text)for node in root:data_list.append(node.text)return data_listresult = xml_to_list("北京") print(result)
-
返回值可以是任意类型,如果函数中没写return,则默认返回None
# 返回值可以是任意类型 def func():return [1, True, (11, 22, 33,)]result = func() print(result) # [1, True, (11, 22, 33)]
# 未写返回值 或 return 或 return None,执行函数获取的返回值都是None def func2():value = 1 +1ret = func2() print(ret) # None
-
return后面的值如果有逗号,则默认会将返回值转换元组再返回
# 后面的值有逗号,默认返回值转成元组返回 def func3():return 1, 2, 3value = func3() print(value) # (1, 2, 3)
-
函数一旦遇到return就会立即退出函数(终止函数中的所有代码)
# 遇到return就立即推出函数 def func4():print(1)return "结束吧"print(2)ret = func4() # 1 print(ret) # 结束吧
2.函数进阶
1.1参数的补充
'''
Python参数的特性有两个好处:1.节省内存2.对于可变类型且函数中修改元素的内容,所有的地方都会修改。可变类型: 列表、字典、集合
'''
name = "Tom"
print(id(name)) # 2957232352080
func5(name) # Tom 2957232352080# 可变类型 & 修改内部元素
def func6(data):data.append(666)list_num = [11, 22, 33]
# id()查看列表的地址
print(id(list_num)) # 1207590744832
func6(list_num)
print(id(list_num)) # 1207590744832
print(list_num) # [11, 22, 33, 666]# 可变类型 & 重新赋值
def func7(data):data = ["Python", "JAVA"]list_v1 = [11, 22, 33]
# id()获取地址,地址一样
print(id(list_v1)) # 2448412623744
func7(list_v1)
print(id(list_v1)) # 2448412623744
print(list_v1) # [11, 22, 33]
1.函数的返回值是内存地址
def func8():data = [11, 22, 33]print(id(data))return datanum_list_1 = func8() # 2345095810048
print(num_list_1, id(num_list_1)) # [11, 22, 33] 2345095810048num_list_3 = func8() # 2345095381376
print(num_list_3, id(num_list_3)) # [11, 22, 33] 2345095381376
2.参数的默认值
def func9(a1, a2=18):print(id(a1), id(a2))print(a1, a2)# 执行函数未传值时,a2指向函数维护的内存地址
func9("root") # 140734791238752 140734792256472 root 18
# 执行函数传值时,a2指向新传入的值,内存地址指向新地址
func9("root", 20) # 140734791238752 140734792256536 root 20
-
注意事项
-
默认参数的值时可变类型列表、字典、集合,函数内部修改这个默认值,地址发生改变
a2 = [11, 22] print(id(a2)) # 2692011379456def func10(a1, a2):a2.append(a1)print(id(a2)) # 2692010932096return a2str_list = func10("Ailke", ["Python", "JAVA"]) print(id(str_list)) # 2692010932096 print(str_list) # ['Python', 'JAVA', 'Ailke']
-
3.动态参数
-
动态参数,定义函数时在形参位置用 * 或 ** 可以接受任意个参数
def func11(*args, **kwargs):print(args, kwargs)func11("Python", "JAVA", name="Ailke", age=18) # ('Python', 'JAVA') {'name': 'Ailke', 'age': 18}
-
在定义函数时可以用 * 和 **,其实在执行函数时,也可以用
-
形参固定,实参用* 和 **
def func12(a1, a2):print(a1, a2)func12(11,12) # 11 12 func12(a1=12, a2=15) # 12 15 func12(*[11, 33]) # 11 33 func12(**{"a1": 12, "a2": 18}) # 12 18
-
形参用* 和 *,实参也用 * 和 *
def func13(*args, **kwargs):print(args, kwargs)func13(*[11, 22, 33], **{"name": "Ailke", "addr": "成都市"}) # (11, 22, 33) {'name': 'Ailke', 'addr': '成都市'}
# 字符串格式化format str = "我在{},简单地{}".format("成都市", "活着") str = "我在{addr},简单地{status}".format(addr="成都市", status="活着")str = "我在{},简单地{}".format(*["成都市", "活着"]) str = "我在{addr},简单地{status}".format(**{"addr":"成都市", "status":"活着")
-
1.2函数和函数名
-
函数名其实就是一个变量,这个变量只不过代指的函数而已
-
函数必须先定义才能被调用执行
def add(num1, num2):return num1 + num2 result = add(*[22, 44]) print(result) # 66
1.函数做元素
-
函数同时也可被哈希,所以函数名通常也可以做 集合的元素、字典的键
def send_message(phone, content):passdef send_image(img_path, content):passdef send_emoji(emoji):passdef send_file(path):passfunction_dict = {"a": [send_message, ['132***56985', '您好!']],"b": [send_image, ['**/**/**.jpeg', '消息内容']],"c": [send_emoji, ["😁"]],"d": [send_file, ['**.Zz']]}print("a.发消息 b.发图片 c.发表情 d.发送文件".center(30, "*")) choice = input("请选择: ")item = function_dict.get(choice) if not item:print("输入错误") else:func = item[0]param_list = item[1]func(*param_list)
2函数名赋值
-
函数名赋值给其他变量,函数名其实就个变量,代指某函数;如果将函数名赋值给另一个变量,则此变量也会代指该函数
def func(a1, a2):print(a1, a2)newFunc = func func(1, 2) newFunc(2, 3)
-
对函数名重新赋值,如果将函数名修改为其他值,函数名便不再代指函数
def func(a1, a2):print(a1, a2)#执行func函数 func(11, 12)# func重新赋值成一个字符串 func = "ailke" print(func) # ailke
-
注意点: 由于函数名被重新定义之后,就会变成被定义的值,在实际的项目开发中,自定义函数时,不要与python内置的函数同名,否则会覆盖内置函数
id(), bin(), hex(), oct(), len(), ...
# len()内置函数用于计算长度 strNum = len("Python") print(strNum) # 5# 下面的错误示范,len()重新定义成另一个函数 def len(a1, a2):return a1 + a2# 以后执行len()函数,只能按照重新定义来使用 print(len(11, 22)) # 33
3.函数名做参数和返回值
-
函数名其实就一个变量,代指某个函数;和其他的数据类型一样,也可以当作函数的参数和返回值
-
参数
# 参数 def plus(num):return num + 100def handler(func):result = func(10)msg = "执行func,并获取到的结果为:{}".format(result)print(msg) # 执行func,并获取到的结果为:110handler(plus)
-
返回值
# 返回值 def diff(num):return num - 10def handler2():print("执行handler函数") # 执行handler函数return diffresult = handler2() print(result(20)) # 10
-
1.3返回值和print
-
在函数中使用print,只是用于在某个位置输出内容
-
在函数中使用return,是为了将函数得执行结果返回给调用者,以便于后续其他操作
def add(num1, num2):print(num1 + num2) # 30result = add(10, 20) print(result) # Nonedef add(num1, num2):return num1 + num2result = add(22, 33) print(result) # 55
1.4作用域
- 作用域,可以理解为一块空间,空间的数据是可以共享的
1.函数为作用域
-
Python以函数为作用域,在函数内创建的所有数据,可以在函数中被使用,无法在其他函数中被使用
def func():name = "Ailke"data_list = [11, 22, 33]print(name, data_list) # Ailke [11, 22, 33]age = 20print(age) # 20def handler():age = 18print(age) # 18func() handler()
2.全局和局部
-
Python中以函数为作用域,函数的作用域其实是一个局部作用域
goods = [{"name": "笔记本", "price": 6999},{"name": "手机", "price": 5999},{"name": "游艇", "price": 8660000},{"name": "显示器", "price": 2299} ]for index in range(len(goods)):item = goods[index]print(index + 1, item['name'], item['price'])while True:num = input("请输入要选择的商品序号(Q/q): ")if num.upper() == "Q":breakif not num.isdecimal():print("用输入的格式错误!")breaknum = int(num)if num > 4 or num < 0:print("范围选择错误!")breaktarget_index = num - 1choice_item = goods[target_index]print(choice_item['name'], choice_item['price'])
-
全局变量
COUNTRY
和CITY_LIST
是在全局作用域,全局作用域中创建的变量称为全局变量,可以在全局作用域中被使用,也可以在局部作用域被使用- 全局变量一般都是大写
# 全局变量 COUNTRY = "中国" CITY_LIST = ["北京", "上海", "深圳", "成都"]def download():# 局部变量url = "https://www.12306.cn"print(url)print(COUNTRY)print(CITY_LIST)def upload():# 局部变量file_name = "rose.zip"print(file_name)print(COUNTRY)print(CITY_LIST)print(COUNTRY) print(CITY_LIST) download() upload()# print(file_name) # 报错 # print(url) # 报错
3.global关键词
-
默认情况下,在局部作用域对全局变量只能进行: 读取 和 修改内部元素 (可变类型),无法对全局变量进行重新赋值
-
读取
# 全局变量 COUNTRY = "中国" CITY_LIST = ["北京", "上海", "深圳", "成都"]def download():# 局部变量url = "https://www.12306.cn"print(url)print(COUNTRY)print(CITY_LIST)download()
-
修改内部元素(可变类型)
# 全局变量 COUNTRY = "中国" CITY_LIST = ["北京", "上海", "深圳", "成都"]def download():# 局部变量url = "https://www.12306.cn"print(url)print(COUNTRY)CITY_LIST.append("重庆")CITY_LIST[0] = "西安"print(CITY_LIST)download()
-
无法对全局变量重新赋值
COUNTRY = "中国" CITY_LIST = ["北京", "成都", "上海", "深圳"]def download():url = "https://www.12306.cn"CITY_LIST = ["四川省", "陕西", "重庆"]print(CITY_LIST) # ['四川省', '陕西', '重庆']download() print(CITY_LIST) # ['北京', '成都', '上海', '深圳']
-
-
局部作用域中对全局变量重新赋值,则可以基于 global关键字 实现
COUNTRY = "中国" CITY_LIST = ["北京", "成都", "上海", "深圳"]def download():url = "https://www.12306.cn"global CITY_LISTCITY_LIST = ["河北省", "山西省", "山东省"]print(CITY_LIST) # ['河北省', '山西省', '山东省']global COUNTRYCOUNTRY = "中华人民共和国"print(COUNTRY) # 中华人民共和国download() print(CITY_LIST) # ['河北省', '山西省', '山东省']
4.nonlocal关键字
def outer_function():x = 12def inner_function():nonlocal x# 此处添加nonlocal关键字,不是创建新的变量x,是修改变量xx = 20print("inner_function:", x) # inner_function: 20inner_function()print("outer_function: ", x) # outer_function: 20outer_function()
3.函数高级
1.函数嵌套
-
Python中以函数为作用域,在作用域中定义的相关数据只能被 当前作用域 或 子作用域使用
userName = "Ailke" print(userName) # Ailkedef func():print(userName)func() # Ailke
1.1函数的作用域中
-
函数也是定义在作用域中的数据,在执行函数时候,也同样遵循: 优先在自己作用域中寻找,没有则向上一级作用域寻找
# 1.在全局作用域定义了函数func def func():print("上一级作用域")# 2.在全局作用域找到func函数并执行 func() # 上一级作用域# 3.在全局作用域定义了execute函数 def execute():print("局部作用域开始") # 局部作用域开始# 优先在当前函数作用域func函数,没有则向上级作用域中寻找func() # 上一级作用域print("局部作用域结束") # 局部作用域结束# 4.在全局作用域执行execute函数 execute()
1.2函数定义的位置
-
函数均定义在全局作用域,其实函数也可以定义在局部作用域,函数被局部作用域和其子作用域中调用(函数的嵌套)
def func():print("全局作用域")def handler():print("全局作用域2")def inner():print("局部作用域")inner()func()print("全局作用域3")''' 全局作用域2 局部作用域 全局作用域 全局作用域3 ''' handler()
1.3嵌套引发的作用域问题
- 优先在自己的作用域找变量,自己没有就去上级作用域
- 在作用域中寻找值时,确保此时此刻的值是什么
- 分析函数的执行,并确定函数 作用域链 (函数嵌套)
userName = "李四"def run():userName = "ailke"def inner():print(userName)return inner'''
ailke
None
'''
userNAME = run()
print(userNAME())'''
ailke
None
'''
userNAME = run()
print(userNAME())
2.闭包
- 闭包,简而言之就是将数据封装在一个包(区域)中,使用时再去里面取
- 闭包是基于函数嵌套弄出来的一个特殊嵌套
1.封装数据防止污染全局
def func(age):userName = "赵六"def f1():print(userName, age)def f2():print(userName, age)def f3():print(userName, age)def f4():print(userName, age)f1()f2()f3()f4()func(18)
2.封装数据封到一个包里,使用时再取
def task(arg):def inner():print(arg)return innerinner_func_list = []
for val in [11, 22, 33]:inner_func_list.append(task(val))inner_func_list[0]() # 11
inner_func_list[1]() # 22
inner_func_list[2]() # 33
3.装饰器
-
装饰器,在不修改原函数内容的前提下,通过 @ 函数可以实现在函数前后自定义执行一些功能
-
实现效果
- 可以在不改变原函数内部代码 和 调用方式的前提下,实现函数执行和执行扩展功能
-
实现原理
- 基于 @语法 和函数闭包,将原函数封装在闭包中,然后将函数赋值为一个新的函数(内层函数),执行函数时再在内层函数中执行闭包中的原函数
def func():print("我是func函数")value = [11, 22, 33]return valuedef outer(origin):def inner():print('before')res = origin()print('after')return resreturn innerfunc = outer(func) print(func) # <function outer.<locals>.inner at 0x00000274D6164220> # 等效输出 inner() result = func()def outers(origin):def inner():print('before')res = origin()print('after')return resreturn inner@outers def func():print('我是func函数')value = [11, 22, 33]return valuefunc()
-
优化
-
优化以支持多个参数
def outer(origin):def inner(*args, **kwargs):print('before')res = origin(*args, **kwargs)print('after')return resreturn inner@outer def func1(a1):print("我是func1()函数")value = [11, 22, 33]return value@outer def func2(a1, a2):print("我是func2()函数")value = [11, 22, 33]return value@outer def func3(a3):print("我是func3()函数")value = [11, 22, 33]return valuefunc1(12) func2(12, a2=18) func3({"name": "Ailke", "addr": "成都市"})
-
1.functools
-
装饰器实际上就是将原函数更改为其他函数,然后再此函数中再去调用原函数
-
不用functools也可以实现装饰器的基本功能,但是后期实际项目开发时,不加functools会出错(内部会读取___name_原函数,name重名的话就报错)
import functoolsdef handler():passhandler() # 读取当前函数名称 print(handler.__name__) # handlerdef auth(func):def inner(*args, **kwargs):return func(*args, **kwargs)return inner@auth def handler():passhandler() # 读取当前函数名称 print(handler.__name__) # innerdef auth_update(func):@functools.wraps(func)def inner(*args, **kwargs):return func(*args, **kwargs)return inner@auth_update def handler():passhandler() # 读取当前函数名称 print(handler.__name__) # handler
4.内置函数和推导式
1.匿名函数
-
传统的函数的定义包括了: 函数名 + 函数体
def send_email():pass# 执行 send_email() # 当作列表元素 # data_list = [send_email, send_email, send_email] # 当作参数传递 # other_functions(send_email)
-
匿名函数,则是基于lambda表达式现实定义一个可以没有名字的函数
# 匿名函数 data_list = [lambda x: x + 100, lambda x: x + 110, lambda x: x + 120] print(data_list[0](20))
-
基于Lambda定义的函数格式为: lambda 参数: 函数体
-
参数,支持任意参数
lambda x: 函数体 lambda x1, x2: 函数体 lambda *args, **kwargs: 函数体
-
函数体,只能支持单行的代码
def send(x):return x + 100f1 = lambda x: x + 100# 函数体只能支持单行代码 # functions = lambda x: # x + 100print(send(10)) # 110 print(f1(10)) # 110
-
返回值,默认将函数单行代码执行的结果返回给函数的执行
func = lambda x: x + 123value = func(123) print(value) # 246
-
-
扩展: 三元运算
-
简单的函数,可以基于lambda表达式实现
-
简单的条件语句,可以基于三元运算实现
''' 三元运算 - 格式结果 = 条件成立时 if 条件 else 条件不成立时'''# 结合lambda func = lambda x: "大了" if x > 66 else "小了" print(func(99))
-
2.生成器
-
生成器是由函数 + yield关键字创造出来的写法,在特定情况下,可以帮助我们节省内存
-
生成器函数,函数中有yield存在时,函数就是生成器函数
def func():print(112)yield 12
-
生成器对象,执行生成器函数时,会返回一个生成器对象
def func():print(112)yield 12print(func()) # <generator object func at 0x0000021DC6F34940>
-
生成器的特点是,记录在函数中的执行位置,下次执行next时,会从上一次的位置基础上继续向下执行
def func():print(112)yield 12print(func()) # <generator object func at 0x0000021DC6F34940>print(next(func()))def funcs():print(111)yield 1print(222)yield 2# StopIteration: 2 error# return 2print(333)yield 3# print(444)data = funcs()print(next(data))print(next(data))print(next(data))
-
应用场景
import randomdef gen_random_num(max_count):counter = 0while counter < max_count:yield random.randint(1000, 9999)counter += 1data_list = list(gen_random_num(30000)) print(type(data_list))print(len(data_list)) print(data_list[8989])
-
知识拓展
def func():print(111)v1 = yield 1print(v1)print(222)v2 = yield 2print(v2)print(333)v3 = yield 3print(v3)print(444)data = func()''' send()方法的作用:- 发送一个值到生成器中,这个值将作为上一个yield表达式的结果;第一次调用生成器的send()方法时,传入None值- 触发生成器继续执行,直到遇到下一个yield语句,并返回该yield语句产出的值- 发送值之后生成器执行完毕(没有更多的yield语句),则send()方法将会引发Stopiteration异常 '''n1 = data.send(None) print(n1)n2 = data.send(666) print(n2)n3 = data.send(777) print(n3)n4 = data.send(888) print(n4)
3.内置函数
# abs 绝对值
print(abs(-10)) # 10# pow 指数
print(pow(2, 3)) # 8# sum 求和
print(sum([1, 2, 3, -10, 12])) # 8# divmod 求商和余数,返回元组类型
print(divmod(9, 2)) # (4, 1)# round,小数点后n位(四舍五入)
print(round(3.1415926, 4)) # 3.1416# min 最小值 def min(*args, key=None):
print(min([12, 56, 8, 10])) # 8# max 最大值
print(max([12, 56, 88], key=lambda x: x * 10))# all 是否全部为True
print(all([11, 22, 33, " ", ""])) # False# any 是否存在True
print(any([11, 22, 33, " ",""])) # True# oct 十进制转八进制
print(oct(125)) # 0o175
# hex 十进制转十六进制
print(hex(125)) # 0x7d
# bin 十进制转二进制
print(bin(125)) # 0b1111101
4.推导式
# 列表
num_list = [i for i in range(10)]
print(num_list) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]# 集合
num_set = {(i, i, i) for i in range(10) if i > 6}
print(num_set) # {(8, 8, 8), (7, 7, 7), (9, 9, 9)}# 字典
num_dict = {i: (i, 11) for i in range(10) if i >= 6}
print(num_dict) # {6: (6, 11), 7: (7, 11), 8: (8, 11), 9: (9, 11)}# 元组,不同于其他类型
# 不会立即执行内部循环去生成数据,而是得到一个生成器
num_tup = (i for i in range(10))
print(num_tup) # <generator object <genexpr> at 0x0000025B35546A40>
print(next(num_tup)) # 0
print(next(num_tup)) # 1
2.模块
1.自定义模块
1.1模块和包
import hashlibdef encrypt(data):'''数据加密'''hash_object = hashlib.md5()hash_object.update(data.encode('utf-8'))return hash_object.hexdigest()userName = input("Enter your username:")
pwd = input("Enter your password:")
md5_password = encrypt(pwd)
message = "用户名:{},密码:{}".format(userName,md5_password)
print(message)
- 简单的程序,可以通过一个py文件编写完成;对于程序比较庞大,此时就需要代码结构清晰
- 在Python中一般对文件和文件的称呼
- 一个py文件,称为模块(Module)
- 含多个py文件的文件夹,称为包(package)
- 注意: 在包(文件夹)中有一个默认内容为空的___init___.py的文件,一般用于描述当前包的信息
- py2必须有,如果没有导入包就会失败
- py3可有可无
1.2导入
-
导入,其实就是将模块或包加载的内存中,以后再去内存中去拿就行
-
在Python内部默认设置了一些路径,导入模块或包时,都会按照指定顺序逐一去特定的路径查找
-
手动设置路径,进行包的导入,**sys.path()**中添加路径
import sys sys.path.append("指定路径")# 导入指定路径下的一个***.py文件 import ***
- 写模块名称时,不能和内置和第三方的同名
- 项目执行文件一般在项目根目录,执行文件嵌套的内存目录,就需要自己手动在sys.path中添加路径
- pycharm中默认会将项目目录加入到sys.path中
-
第一类方式: **import *****(开发中,一般多用于导入sys.path目录下的一个py文件)
''' |---commons | |---- __init__.py | |---- tools | |---- __init__.py | |---- sum.py |---main.py'''import commons.utils import commons.tools.sumuserName = input("Enter your username:") pwd = input("Enter your password:") # md5_password = utils.encrypt(pwd) md5_password = commons.utils.encrypt(pwd) message = "用户名:{},密码:{}".format(userName,md5_password) print(message)print("输入数据和: ", commons.tools.sum.sum_itme([12, 13, 14])) print("输入数据和: ", commons.tools.sum.sum_itme((12, 15, 16,))) print("输入数据和: ", commons.tools.sum.sum_itme(12.45))import hashlibdef encrypt(data):'''数据加密'''hash_object = hashlib.md5()hash_object.update(data.encode('utf-8'))return hash_object.hexdigest()def sum_itme(items):if isinstance(items, (int, float)):items = [items]elif not isinstance(items, (list, tuple)):raise TypeError("The input must be a number or a list of numbers")return sum(items)
-
第二类方式: from ******* import *******(常用),一般适用于多层嵌套和导入模块中某个成员的情况
''' |---commons | |---- __init__.py | |---- tools | |---- __init__.py | |---- sum.py |---main.py'''from commons import utils from commons.tools import sum # import commons.utils # import commons.tools.sumuserName = input("Enter your username:") pwd = input("Enter your password:") # md5_password = utils.encrypt(pwd) md5_password = utils.encrypt(pwd) message = "用户名:{},密码:{}".format(userName,md5_password) print(message)print("输入数据和: ", sum.sum_itme([12, 13, 14])) print("输入数据和: ", sum.sum_itme((12, 15, 16,))) print("输入数据和: ", sum.sum_itme(12.45))# print("输入数据和: ", commons.tools.sum.sum_itme([12, 13, 14])) # print("输入数据和: ", commons.tools.sum.sum_itme((12, 15, 16,))) # print("输入数据和: ", commons.tools.sum.sum_itme(12.45))import hashlibdef encrypt(data):'''数据加密'''hash_object = hashlib.md5()hash_object.update(data.encode('utf-8'))return hash_object.hexdigest()def sum_itme(items):if isinstance(items, (int, float)):items = [items]elif not isinstance(items, (list, tuple)):raise TypeError("The input must be a number or a list of numbers")return sum(items)
1.3相对导入
-
在导入模块时,对于from ******* import *** 这种模式,还支持相对导入
''' mypackage/ __init__.py module_a.py subpackage/ __init__.py module_x.py module_y.py ''' # 从module_a.py导入module_x.py from .subpackage import module_x# 从module_x.py导入module_a.py from .. import module_a
-
**.代表当前包,…**代表父级包,相对导入只能用在包中的py文件中
1.4导入别名
-
项目在导入 成员、模块、包 有重名,那么导入后会覆盖之前的导入,为了避免这种情况的发生,Python支持重命名
# 两种导入方式都可重命名 from ***.*** import *** as ** import ***.*** as **
1.5主文件
-
执行一个py文件时
__name__ = "__main__"
-
导入一个py文件时
__name__ = "模块名"
-
文件内部__name__变量的值为__main___,以主文件的形式允许此脚本时start函数才会被执行,被导入时则不会被执行
if __name__ == '__main__':start()
2.第三方模块
1.pip (最常用)
-
pip其实是个第三方模块包管理工具,默认安装Python解释器时自动会安装,默认目录
''' windows系统,即: Python安装路径的scripts目录下- C:\**\Scripts\pip3.exe- C:\**\Scripts\pip.版本号.exe'''
-
pip安装模块,默认安装最新版本
# 默认安装 pip3 install 模块名称# 指定版本安装 pip3 install 模块名称==版本
-
pip更新版本
# 查看当前版本 pip3 --version# 更新 pip3 install --upgrade pip
2.豆瓣源
-
pip默认是去https://pypi.org去下载第三方模块,国内下载可能出现问题,为了加速下载可以使用豆瓣源
-
一次性使用下载
# 如果按照一下指令显示对源不信任,在末尾加上--trusted-host pypi.douban.com pip3 install 模块名称 -i https://pypi.douban.com/simple
-
永久使用
- 配置
# 替换主机下载路径 pip3 config set global.index-url https://pypi.douban.com/simple/ ''' 国内常用的镜像- 阿里云:http://mirrors.aliyun.com/pypi/simple/- 中国科技大学:https://pypi.mirrors.ustc.edu.cn/simple/ - 清华大学:https://pypi.tuna.tsinghua.edu.cn/simple/-中国科学技术大学:http://pypi.mirrors.ustc.edu.cn/simple/'''
- 使用
pip3 install 模块名称
3.源码
-
下载源码安装模块
-
下载源码
# 1.不管是GitHub或网站下载,需要解压的首先解压 # 2.进入到目录 # 3.运行命令 # # 编译 python setup.py build # # 安装 python setup.py install
-
4.wheel
-
下载wheel文件
- 从某个源下载模块的wheel文件,wheel的文件扩展命通常是.whl
-
安装wheel包
# 需要安装wheel pip3 install wheel
-
使用pip安装wheel文件
pip3 install 模块名称.whl
3.内置模块
1.os
import os.path# 获取当前脚本绝对路径
abs_path = os.path.abspath(__file__)
print(abs_path) # C:\Tools\devTools\Pycharm\code\内置模块\main.py# 获取当前文件的上级目录
parent_path = os.path.dirname(abs_path)
print(parent_path) # C:\Tools\devTools\Pycharm\code\内置模块# 路径拼接
print(os.path.join(parent_path, "test.txt")) # C:\Tools\devTools\Pycharm\code\内置模块\test.txt# 判断路径是否存在
print(os.path.exists(os.path.join(parent_path, "test.txt"))) # False
print(os.path.exists(os.path.join(parent_path, "main.py"))) # True# 创建路径
os.makedirs(os.path.join(parent_path, "test"), exist_ok=True)
print(os.path.exists(os.path.join(parent_path, "test"))) # True# 是否是文件夹
print(os.path.isdir(os.path.join(parent_path, "test"))) # True
print(os.path.isdir(os.path.join(parent_path, "test.txt"))) # False# 删除文件或文件夹
os.remove(os.path.join(parent_path, "test.txt"))
print(os.path.exists(os.path.join(parent_path, "test.txt"))) # Falseos.rmdir(os.path.join(parent_path, "test"))
print(os.path.exists(os.path.join(parent_path, "test"))) # False# 创建文件
# 'w'模式表示写入模式,如果文件不存在,则会创建该文件
with open(os.path.join(parent_path, "test.txt"), "w", encoding="utf-8") as f:f.write("hello world")
print(os.path.exists(os.path.join(parent_path, "test.txt"))) # True# 查看目录下所有的文件
print(os.listdir(os.path.join(parent_path, "test"))) # ['test.txt', 'txt']# 查看目录下所有的文件(含子孙文件)
data = os.walk(os.path.join(parent_path, "test"))
for path, folder_list, file_list in data:print(path)print(folder_list)print(file_list)# for file_name in file_list:# file_abs_path = os.path.join(path, file_name)# print(file_abs_path)# for folder_name in folder_list:# folder_abs_path = os.path.join(path, folder_name)# print(folder_abs_path)## for path_name in path:# print(path_name)
2.shutil
import shutil
import os# 获取当前脚本的绝对位置
abs_path = os.path.abspath(__file__)# 获取当前位置的上一级目录
base_path = os.path.dirname(abs_path)
print(base_path) # C:\Tools\devTools\Pycharm\code\内置模块
print(os.getcwd()) # C:\Tools\devTools\Pycharm\code\内置模块
# 删除文件夹
shutil.rmtree(os.path.join(os.getcwd(), 'study'))# 拷贝文件夹 拷贝的目标地址,如果存在就会报错
shutil.copytree(os.path.join(base_path, "test"), os.path.join(os.getcwd(), 'studentInfo'))# 拷贝文件
shutil.copy(os.path.join(abs_path), os.path.join(os.getcwd(), 'study'))# 文件或文件夹重命名
shutil.move(os.path.join(os.getcwd(), "study/main.py"), os.path.join(base_path, "study/info.py"))# 压缩文件
shutil.make_archive(base_name=r'dataFile', format='zip', root_dir=os.path.join(base_path, 'studentInfo'))# 解压文件
shutil.unpack_archive(filename=r'dataFile.zip', extract_dir=os.path.join(os.getcwd(), "study"), format='zip')
3.sys
import sys# 获取解释器版本
print(sys.version)
print(sys.version_info)
print("Python主版本号:", sys.version_info.major, ",Python此版本号:", sys.version_info.minor, ",Python微版本号:",sys.version_info.micro,",Python发行级别:", sys.version_info.releaselevel, ",Python发行序列号:", sys.version_info.serial)
# 导入模块路径
print(sys.path)
4.random
import random# 获取范围内的随机整数
print(random.randint(10, 20))# 获取范围内的随机小数
print(random.uniform(10, 20))# 随机抽取一个元素
print(random.choice([11, 22, 23, 56, 89]))# 随机抽取多个元素
print(random.sample([11, 55, 66, 23, 56, 89], 3))# 打乱顺序
data = [1, 2, 3, 4, 5, 6]
random.shuffle(data)
print(data)
5.hashlib
6.configparser
- 见下文
7.xml
- 见下文
3.文件操作
1.文件操作
-
字符串类型(str),在程序中用于表示文字信息,本质上是unicode编码中的二进制
str = "Python"
-
字节类型
-
可表示文字信息,本质上是utf-8/gbk等编码的二进制
strInfo = "Python" data = strInfo.encode("utf-8") # b'Python' print(data)result = data.decode("utf-8") print(result) # Python
-
可表示原始二进制(图片、文件等信息)
-
1.读文件
- 读文本文件
# 打开文件
'''
mode是一个可选字符,默认值为 r,打开文本阅读模式- w 表示写入(截断文件)- x 表示用于创建喝写入新文件- a 表示追加(在某些Unix系统上,表示所有写入),追加到文件的末尾- b 表示二进制模式- t 表示文本模式(默认)- + 打开磁盘文件进行更新(读写)'''
import os.path# 打开文件
file_object = open(os.path.join(os.getcwd(), "test") + "/test.txt", mode='rb')
# 读取文件内容,并赋值给data
data = file_object.read()
# 关闭文件
file_object.close()# 输出文件内容(二进制)
print(data)
# 解码
text = data.decode('utf-8')
print(text)# # 打开文件
# file_object = open(os.path.join(os.getcwd(), "test") + "/test.txt", mode='rt',encoding='utf-8')
# # 读取文件内容,并赋值给data
# data = file_object.read()
# # 关闭文件
# file_object.close()
#
# print(data)
-
读图片等非文本内容文件
# 打开文件 file_object = open(os.path.join(os.getcwd(), "test") + "/python安装检验.png", mode="rb") # 读取文件内容,并赋值给data data = file_object.read() # 关闭文件 file_object.close() # 打印二进制码 print(data)
-
读文件时,文件不存在程序会报错
file_path = os.path.join(os.getcwd(), "test/test.txt") exists = os.path.exists(file_path) if exists:# 打开文件file_object = open(file_path, mode='rt', encoding='utf-8')# 读取文件内容,并赋值给datadata = file_object.read()# 关闭文件file_object.close()print(data) else:print("文件不存在!")
2.写文件
# 写文件文本
# 打开文件 用二进制方式输入
# file_object = open(os.path.join(os.getcwd() + "/test/txt.txt"), mode="wb")
# 用文本方式输入 w模式会新建,然后再写入内容;文件存在时,w模式会清空文件再写入内容
file_object = open(os.path.join(os.getcwd() + "/test/text.txt"), mode="wt", encoding='utf-8')# 写入内容
# file_object.write("新公司真不错".encode("utf-8"))
file_object.write("新公司业务好")# 文件关闭
file_object.close()# 写图片等文件
f1 = open(os.path.join(os.getcwd() + "/test/python安装检验.png"), mode='rb')
content = f1.read()
f1.close()f2 = open(os.path.join(os.path.dirname(os.path.abspath(__file__)) + "/test/python安装检验_copy.png"), mode='wb')
f2.write(content)
f2.close()# 案例: 多用户注册
# 新建文件夹
os.makedirs(os.path.join(os.getcwd(), "files"), exist_ok=True)
file_object = open(os.path.join(os.getcwd() + "/files/info.txt"), mode="wt", encoding="utf-8")
while True:user = input("请输入用户名:")if user.upper() == "Q":breakpwd = input("请输入密码:")data = "{}----{}".format(user, pwd)file_object.write(data + "\n")
file_object.close()
3.文件打开模式
-
基于文件操作基本实现了读、写的功能,其中涉及的文件操作模式: rt 、rb、wt、wb,其实再文件操作还有其他很多模式
Character Meaning--------- ---------------------------------------------------------------'r' open for reading (default)'w' open for writing, truncating the file first'x' create a new file and open it for writing'a' open for writing, appending to the end of the file if it exists'b' binary mode't' text mode (default)'+' open a disk file for updating (reading and writing) The default mode is 'rt' (open for reading text)
-
文件的打开模式常见应用有
-
只读: r 、rt 、rb
- 存在,读
- 不存在,报错
-
只写: w、wt、wb
- 存在,清空再写
- 不存在,创建再写
-
只写: x、xt、xb
- 存在,报错
- 不存在,创建再写
-
只写: a、at、ab
- 存在,尾部追加
- 不存在,创建再写
-
读写:
-
r+、rt+、rb+
-
默认光标位置,起始位置
# rt+ # 打开文件 file_object = open(os.path.join(os.getcwd() + "/files/infos.txt"), mode="rt+") # 读取文件 data = file_object.read() print(data)# 写入内容 file_object.write("你好呀")file_object.close()
-
w+、wt+、wb+,默认光标位置,为起始位置(清空文件)
# wt+ # 打开文件 file_object = open(os.path.join(os.getcwd() + "/files/info.txt"), mode="wt+")# 读取文件 data = file_object.read() print(data) # # 写入内容 file_object.write("你好呀")# 重置光标起始位置 file_object.seek(0)# 读取文件 data = file_object.read() print(data) # 你好呀file_object.close()
-
x+、xt+、xb+,默认光标位置: 起始位置(新文件)
-
a+、at+、ab+,默认光标位置: 末尾
# at+ # 打开文件 file_object = open(os.path.join(os.getcwd() + "/files/info.txt"), mode="at+")# 写入内容 file_object.write("你好呀")# 重置光标起始位置 file_object.seek(0)# 读取文件 data = file_object.read() print(data) # 你好呀file_object.close()
-
-
4.常见功能
-
read,读
-
读所有
# 读取二进制模式下,不需要设置字符编码 file_object = open(os.path.join(os.getcwd() + "/files/info.txt"), mode="r", encoding='utf-8') data = file_object.read() file_object.close()
-
读n个字符(字节)
# 读取二进制模式下,不需要设置字符编码 file_object = open(os.path.join(os.getcwd() + "/files/info.txt"), mode="r", encoding='utf-8') # 读一个字符 data = file_object.read(1) file_object.close()# 读取二进制模式下,不需要设置字符编码 file_object = open(os.path.join(os.getcwd() + "/files/info.txt"), mode="rb") # 读一个字节;编码格式为utf-8,参数输入3,表示读取一个字符 data = file_object.read(1) file_object.close()
-
readline,读一行
# 读取二进制模式下,不需要设置字符编码 file_object = open(os.path.join(os.getcwd() + "/files/info.txt"), mode="r", encoding='utf-8') data = file_object.readline() file_object.close()
-
readlines,读所有行,每行作为列表的一个元素
# 读取二进制模式下,不需要设置字符编码 file_object = open(os.path.join(os.getcwd() + "/files/info.txt"), mode="r", encoding='utf-8') data_list = file_object.readlines() file_object.close()
-
循环,读大文件
# 读取二进制模式下,不需要设置字符编码 file_object = open(os.path.join(os.getcwd() + "/files/info.txt"), mode="r", encoding='utf-8') for line in file_object:print(line.strip()) file_object.close()
-
-
write,写
# 打开文件 file_object = open(os.path.join(os.getcwd() + "/files/info.txt"), mode="a", encoding="utf-8")# 写入内容 file_object.write("你好呀")file_object.close()# 打开文件 file_object = open(os.path.join(os.getcwd() + "/files/info.txt"), mode="ab")# 写入内容 file_object.write("你好呀".encode("utf-8"))file_object.close()
-
flush,刷到硬盘
# 打开文件 file_object = open(os.path.join(os.getcwd() + "/files/info.txt"), mode="ab")# 写入内容 file_object.write("你好呀".encode("utf-8")) # 缓冲区刷到硬盘 file_object.flush()file_object.close()
-
移动光标位置(字节)
- 在a模式下,调用write在文件中写入内容,永远只能将内容写入尾部,不会写到光标位置
# 打开文件 file_object = open(os.path.join(os.getcwd() + "/files/info.txt"), mode="r+", encoding="utf-8")# 移动光标位置,(UTF-8)编码格式,按照每3个字节为一个单位移动 file_object.seek(3) # 写入内容 file_object.write("你好呀") # 缓冲区刷到硬盘 file_object.flush()file_object.close()
-
获取当前光标位置
# 打开文件 file_object = open(os.path.join(os.getcwd() + "/files/info.txt"), mode="r", encoding="utf-8")# 获取光标位置 0 file_object.tell()# 读取三个字符 file_object.read(3)# 获取光标位置 3 * 3 = 9 file_object.tell()file_object.close()
5.上下文管理
-
进行文件操作时,使用with上下文管理,可以自动实现关闭文件
# Python2.7之后,支持同时多个文件的上下文管理 with open(os.path.join(os.getcwd() + "/files/info.txt"), mode="r", encoding="utf-8") as f1, open(os.path.join(os.getcwd() + "/files/infos.txt"), mode="rb") as fb:pass
2.csv格式文件
-
逗号分隔值(csv,也称为字符分隔值),其文件以纯文本形式存储表格数据
-
文本
26044585,Hush,https://hbimg.huabanimg.com/51d46dc32abe7ac7f83b94c67bb88cacc46869954f478-aP4Q3V 19318369,柒十一,https://hbimg.huabanimg.com/703fdb063bdc37b11033ef794f9b3a7adfa01fd21a6d1-wTFbnO 15529690,Law344,https://hbimg.huabanimg.com/b438d8c61ed2abf50ca94e00f257ca7a223e3b364b471-xrzoQd 18311394,Jennah·,https://hbimg.huabanimg.com/4edba1ed6a71797f52355aa1de5af961b85bf824cb71-px1nZz 18009711,可洛爱画画,https://hbimg.huabanimg.com/03331ef39b5c7687f5cc47dbcbafd974403c962ae88ce-Co8AUI 30574436,花姑凉~,https://hbimg.huabanimg.com/2f5b657edb9497ff8c41132e18000edb082d158c2404-8rYHbw 17740339,小巫師,https://hbimg.huabanimg.com/dbc6fd49f1915545cc42c1a1492a418dbaebd2c21bb9-9aDqgl 18741964,桐末tonmo,https://hbimg.huabanimg.com/b60cee303f62aaa592292f45a1ed8d5be9873b2ed5c-gAJehO 30535005,TANGZHIQI,https://hbimg.huabanimg.com/bbd08ee168d54665bf9b07899a5c4a4d6bc1eb8af77a4-8Gz3K1 31078743,你的老杨,https://hbimg.huabanimg.com/c46fbc3c9a01db37b8e786cbd7174bbd475e4cda220f4-F1u7MX 25519376,尺尺寸,https://hbimg.huabanimg.com/ee29ee198efb98f970e3dc2b24c40d89bfb6f911126b6-KGvKes 21113978,C-CLong,https://hbimg.huabanimg.com/7fa6b2a0d570e67246b34840a87d57c16a875dba9100-SXsSeY 24674102,szaa,https://hbimg.huabanimg.com/0716687b0df93e8c3a8e0925b6d2e4135449cd27597c4-gWdv24 30508507,爱起床的小灰灰,https://hbimg.huabanimg.com/4eafdbfa21b2f300a7becd8863f948e5e92ef789b5a5-1ozTKq 12593664,yokozen,https://hbimg.huabanimg.com/cd07bbaf052b752ed5c287602404ea719d7dd8161321b-cJtHss 16899164,一阵疯,https://hbimg.huabanimg.com/0940b557b28892658c3bcaf52f5ba8dc8402100e130b2-G966Uz 847937,卩丬My㊊伴er彎,https://hbimg.huabanimg.com/e2d6bb5bc8498c6f607492a8f96164aa2366b104e7a-kWaH68 31010628,慢慢即漫漫,https://hbimg.huabanimg.com/c4fb6718907a22f202e8dd14d52f0c369685e59cfea7-82FdsK 13438168,海贼玩跑跑,https://hbimg.huabanimg.com/1edae3ce6fe0f6e95b67b4f8b57c4cebf19c501b397e-BXwiW6 28593155,源稚生,https://hbimg.huabanimg.com/626cfd89ca4c10e6f875f3dfe1005331e4c0fd7fd429-9SeJeQ 28201821,合伙哼哼,https://hbimg.huabanimg.com/f59d4780531aa1892b80e0ec94d4ec78dcba08ff18c416-769X6a 28255146,漫步AAA,https://hbimg.huabanimg.com/3c034c520594e38353a039d7e7a5fd5e74fb53eb1086-KnpLaL 30537613,配䦹,https://hbimg.huabanimg.com/efd81d22c1b1a2de77a0e0d8e853282b83b6bbc590fd-y3d4GJ 22665880,日后必火,https://hbimg.huabanimg.com/69f0f959979a4fada9e9e55f565989544be88164d2b-INWbaF 16748980,keer521521,https://hbimg.huabanimg.com/654953460733026a7ef6e101404055627ad51784a95c-B6OFs4 30536510,“西辞”,https://hbimg.huabanimg.com/61cfffca6b2507bf51a507e8319d68a8b8c3a96968f-6IvMSk 30986577,艺成背锅王,https://hbimg.huabanimg.com/c381ecc43d6c69758a86a30ebf72976906ae6c53291f9-9zroHF 26409800,CsysADk7,https://hbimg.huabanimg.com/bf1d22092c2070d68ade012c588f2e410caaab1f58051-ahlgLm 30469116,18啊全阿,https://hbimg.huabanimg.com/654953460733026a7ef6e101404055627ad51784a95c-B6OFs4 15514336,W/小哥,https://hbimg.huabanimg.com/a30f5967fc0acf81421dd49650397de63c105b9ead1c-nVRrNl 17473505,椿の花,https://hbimg.huabanimg.com/0e38d810e5a24f91ebb251fd3aaaed8bb37655b14844c-pgNJBP 19165177,っ思忆゜♪,https://hbimg.huabanimg.com/4815ea0e4905d0f3bb82a654b481811dadbfe5ce2673-vMVr0B 16059616,格林熊丶,https://hbimg.huabanimg.com/8760a2b08d87e6ed4b7a9715b1a668176dbf84fec5b-jx14tZ 30734152,sCWVkJDG,https://hbimg.huabanimg.com/f31a5305d1b8717bbfb897723f267d316e58e7b7dc40-GD3e22 24019677,虚无本心,https://hbimg.huabanimg.com/6fdfa9834abe362e978b517275b06e7f0d5926aa650-N1xCXE 16670283,Y-雨后天空,https://hbimg.huabanimg.com/a3bbb0045b536fc27a6d2effa64a0d43f9f5193c177f-I2vHaI 21512483,汤姆2,https://hbimg.huabanimg.com/98cc50a61a7cc9b49a8af754ffb26bd15764a82f1133-AkiU7D 16441049,笑潇啸逍小鱼,https://hbimg.huabanimg.com/ae8a70cd85aff3a8587ff6578d5cf7620f3691df13e46-lmrIi9 24795603,v,https://hbimg.huabanimg.com/a7183cc3a933aa129d7b3230bf1378fd8f5857846cc5-3tDtx3 29819152,妮玛士珍多,https://hbimg.huabanimg.com/ca4ecb573bf1ff0415c7a873d64470dedc465ea1213c6-RAkArS 19101282,陈勇敢❤,https://hbimg.huabanimg.com/ab6d04ebaff3176e3570139a65155856871241b58bc6-Qklj2E 28337572,爱意随风散,https://hbimg.huabanimg.com/117ad8b6eeda57a562ac6ab2861111a793ca3d1d5543-SjWlk2 17342758,幸运instant,https://hbimg.huabanimg.com/72b5f9042ec297ae57b83431123bc1c066cca90fa23-3MoJNj 18483372,Beau染,https://hbimg.huabanimg.com/077115cb622b1ff3907ec6932e1b575393d5aae720487-d1cdT9 22127102,栽花的小蜻蜓,https://hbimg.huabanimg.com/6c3cbf9f27e17898083186fc51985e43269018cc1e1df-QfOIBG 13802024,LoveHsu,https://hbimg.huabanimg.com/f720a15f8b49b86a7c1ee4951263a8dbecfe3e43d2d-GPEauV 22558931,白驹过隙丶梨花泪う,https://hbimg.huabanimg.com/e49e1341dfe5144da5c71bd15f1052ef07ba7a0e1296b-jfyfDJ 11762339,cojoy,https://hbimg.huabanimg.com/5b27f876d5d391e7c4889bc5e8ba214419eb72b56822-83gYmB 30711623,雪碧学长呀,https://hbimg.huabanimg.com/2c288a1535048b05537ba523b3fc9eacc1e81273212d1-nr8M4t 18906718,西霸王,https://hbimg.huabanimg.com/7b02ad5e01bd8c0a29817e362814666a7800831c154a6-AvBDaG 31037856,邵阳的小哥哥,https://hbimg.huabanimg.com/654953460733026a7ef6e101404055627ad51784a95c-B6OFs4 26830711,稳健谭,https://hbimg.huabanimg.com/51547ade3f0aef134e8d268cfd4ad61110925aefec8a-NKPEYX
-
代码
with open(os.path.join(os.getcwd() + "/test/stuInfos.csv"), mode="r", encoding="utf-8") as file_object:file_object.readline()for line in file_object:user_id, userName, url = line.strip().split(",")# 根据URL下载图片res = requests.get(url=url,headers={"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36"})# 检查 images 目录是否存在? 不存在,创建images目录if not os.path.exists(os.getcwd() + "/test/images"):# 创建os.makedirs(os.getcwd() + "/test/images")# 将图片的内容写入文件with open(os.path.join(os.getcwd() + "/test/images/{}.png".format(userName)), mode="wb") as img_object:img_object.write(res.content)
-
3.ini格式文件
-
ini文件时initialzation File的缩写,平时用于存储软件的配置文件
-
文件
[mysqld] datadir=/var/lib/mysql socket=/var/lib/mysql/mysql.sock log-bin=py-mysql-bin character-set-server=utf8 collation-server=utf8_general_ci log-error=/var/log/mysqld.log # Disabling symbolic-links is recommended to prevent assorted security risks symbolic-links=0[mysqld_safe] log-error=/var/log/mariadb/mariadb.log pid-file=/var/run/mariadb/mariadb.pid[client] default-character-set=utf8
-
代码
# 初始化对象 config = configparser.ConfigParser() config.read(os.path.join(os.getcwd() + "/test/my.ini"), encoding="utf-8")# 获取所有节点 result = config.sections() print(result,type(result)) # ['mysqld', 'mysqld_safe', 'client'] <class 'list'># 获取节点下的键值 result = config.items(result[1]) print(result, type(result)) # [('log-error', '/var/log/mariadb/mariadb.log'), ('pid-file', '/var/run/mariadb/mariadb.pid')] <class 'list'>for key,value in config.items("mysqld_safe"):print(key, value)# 获取某个节点下的键对应的值 result = config.get("mysqld_safe", "pid-file") print(result, type(result)) # /var/run/mariadb/mariadb.pid <class'str'># 检查、删除、添加节点 hassection = config.has_section("client") print(hassection) # True# 删除节点,包含该节点下面的键值对 config.remove_section('client')# 删除节点下指定键的键值对 config.remove_option("mysqld", "datadir")# 操作删除之后,需要更新回配置文件中 with open(os.path.join(os.getcwd() + "/test/my.ini"), mode="w", encoding="utf-8") as configFile:config.write(configFile)# 添加节点 config.add_section('server') config.set('server', 'port', '8080') config.set('server', 'ipAddr', '176.0.5.6') config.set('mysqld', 'datadir','/var/lib/mysql')# 添加操作之后,需要更新回配置文件 效果类似于with open... config.write(open(os.path.join(os.getcwd() + "/test/my.ini"), mode='w', encoding='utf-8'))
-
4.XML格式文件
-
可扩展标记语言,是一种捡蛋的数据存储语言,XML被设计用来传输和存储数据
- 存储,可用来存放配置文件
- 传输,网络传输时以这种格式存在
1.读取文件和内容
from xml.etree import ElementTree as ET
# XML格式文件# 打开XML文件
tree = ET.parse(open(os.path.join(os.getcwd() + "/test/data.xml")))# 获取根标签
root = tree.getroot()# 打印根标签
print(root.tag) # data# 代码中的XML解析
content = """
<data><country name="Liechtenstein"><rank updated="yes">2</rank><year>2023</year><gdppc>141100</gdppc><neighbor direction="E" name="Austria" /><neighbor direction="W" name="Switzerland" /></country><country name="Singapore"><rank updated="yes">5</rank><year>2026</year><gdppc>59900</gdppc><neighbor direction="N" name="Malaysia" /></country><country name="Panama"><rank updated="yes">69</rank><year>2026</year><gdppc>13600</gdppc><neighbor direction="W" name="Costa Rica" /><neighbor direction="E" name="Colombia" /></country>
</data>
"""
# 获取根标签
root = ET.XML(content)
print(root.tag) # data
2.读取节点数据
# 读取节点数据
country_object = root.find("country")
# attrib函数获取标签内的属性
print(country_object.tag, country_object.attrib) # country {'name': 'Liechtenstein'}# 获取标签gdppc
gdppc_object = country_object.find("gdppc")
print(gdppc_object.tag, gdppc_object.text) # gdppc 141100# 获取data标签的子标签
for child in root:# 子标签的标签名和标签内部属性print(child.tag, child.attrib)print("单个data标签分割线".center(30, "*"))for node in child:# 子标签内部节点 标签命 标签内部属性 标签的值 无值用None表示print(node.tag, node.attrib, node.text)# 通过根标签指定内部标签,获取内部标签的相关信息
for child in root.iter('rank'):'''rank 2rank 5rank 69'''print(child.tag, child.text)# 查找XML中指定的所有标签
root_son = root.findall("country")
print(root_son) # [<Element 'country' at 0x0000025D2B79FBF0>, <Element 'country' at 0x0000025D2B79FDD0>, <Element 'country' at 0x0000025D2B79FF60>]# 通过find()函数,查找多层标签,仅限查询到的一个符合标签
root_son_str = root.find("country").find("year")
print(root_son_str.tag, root_son_str.attrib, root_son_str.text)
3.修改和删除节点
# 修改节点内容和属性
rank = root.find("country").find("rank")
print(rank.text)
rank.text = "123"
rank.set("update", "no")
print(rank.text, rank.attrib)# 保存配置
tree = ET.ElementTree(root)
tree.write(os.path.join(os.getcwd() + "/test/data.xml"), encoding="utf-8")# 删除节点
root.remove(root.find("country"))
print(root.findall("country"))
# 保存文件
tree = ET.ElementTree(root)
tree.write(os.path.join(os.getcwd() + "/test/data.xml"), encoding="utf-8")
# 笑死,禁忌切勿混合模块
# tree.write(open(os.path.join(os.getcwd() + "/test/data.xml"), mode="w", encoding="utf8"))
4.构建文档
-
student.csv
李四,18,四川省成都市 田六,20,四川省德阳市 王五,27,四川省南充市 Tom,38,NewYork
# 创建根标签
root = ET.Element("studentInfos")
#
# # 创建根标签的子节点
# student1 = ET.Element("student", {"desc": "学生信息"})
# name = ET.Element("name")
# name.text = "张三"
# age = ET.Element("age", {"desc": "Data legitimacy"})
# age.text = "20"
# address = ET.Element("address")
# address.text = "成都市"
# student1.append(name)
# student1.append(age)
# student1.append(address)
#
# student2 = ET.Element("student", {"desc": "学生信息"})
# name = ET.Element("name")
# name.text = "赵六"
# age = ET.Element("age", {"desc": "Data legitimacy"})
# age.text = "25"
# address = ET.Element("address")
# address.text = "上海市"
# student2.append(name)
# student2.append(age)
# student2.append(address)
#
# student3 = ET.Element("student", {"desc": "学生信息"})
# name = ET.Element("name")
# name.text = "李四"
# age = ET.Element("age", {"desc": "Data legitimacy"})
# age.text = "18"
# address = ET.Element("address")
# address.text = "重庆市"
# student3.append(name)
# student3.append(age)
# student3.append(address)
#
# root.append(student1)
# root.append(student2)
# root.append(student3)def create_student_info(username, Age, addr):student = ET.Element("student", {"desc": "学生信息"})name = ET.Element("name")name.text = usernameage = ET.Element("age", {"desc": "Data legitimacy"})age.text = Ageaddress = ET.Element("address")address.text = addrstudent.append(name)student.append(age)student.append(address)return studentwith open(os.path.join(os.getcwd() + "/test/student.csv"), mode="rt", encoding="utf-8") as stu_infos:for stu_info in stu_infos:name, age, addr = stu_info.strip().split(",")root.append(create_student_info(name, age, addr))tree = ET.ElementTree(root)
tree.write(os.path.join(os.getcwd() + "/test/studentInfos.xml"), encoding="utf-8", short_empty_elements=False)
-
studentInfos.xml
<studentInfos><student desc="学生信息"><name>李四</name><age desc="Data legitimacy">18</age><address>四川省成都市</address></student><student desc="学生信息"><name>田六</name><age desc="Data legitimacy">20</age><address>四川省德阳市</address></student><student desc="学生信息"><name>王五</name><age desc="Data legitimacy">27</age><address>四川省南充市</address></student><student desc="学生信息"><name>Tom</name><age desc="Data legitimacy">38</age><address>NewYork</address></student> </studentInfos>
5.Excel格式文件
-
Python内部未提供处理Excel文件的功能,需要按照第三方的模块来处理
pip3 install openpyxl
1.读Excel
-
读sheet
from openpyxl import load_workbook# #sheet # 获取C盘根目录的 # c_drive = os.path.join(os.environ['SystemDrive'])# 获取其他盘根目录 # try: # d_drive = os.path.join('D:\\', '') # print(d_drive) # except OSError: # print("D盘不存在!")wb = load_workbook(os.path.join(os.environ['SystemDrive'], "/Users/梁/Desktop/测试.xlsx")) # 获取excel文件中的所有sheet名称 print(wb.sheetnames) # ['学生信息', '商品价格']# 指定sheet,基于指定的sheet获取指定位置数据 sheet = wb[wb.sheetnames[0]] # wb['学生信息'] 等效 cell = sheet.cell(2, 2) print(cell.value) # username# 指定sheet,基于索引位置 sheet = wb.worksheets[0] cell = sheet.cell(2, 2) print(cell.value) # username# 循环所有的sheet for name in wb.sheetnames:sheet = wb[name]cell = sheet.cell(2, 2)'''username名称'''print(cell.value)for sheet in wb.worksheets:cell = sheet.cell(2, 2)print(cell.value)for sheet in wb:cell = sheet.cell(2, 2)print(cell.value)
-
读sheet中单元格的数据
from openpyxl import load_workbook from openpyxl.worksheet.merge import MergedCellRange# 读取sheet中单元格的数据 # 获取第n行第n列的单元格(单元格计算是1开始) cell = wb.worksheets[0].cell(1, 1) # 单元格的值 print(cell.value) # 单元格的样式 print(cell.style)# 单元格的字体 print(cell.font) # 单元格的单元格中文本的对齐方式 print(cell.alignment)# 获取某一个单元格 value = wb.worksheets[0]['A2'].value print(value) # uidvalue = wb.worksheets[0]['D4'].value print(value) # 56# 获取n行所有单元格 for cell in wb.worksheets[0][2]:print(cell.value)# 获取行的数据(获取某一列的数据) for row in wb.worksheets[0].rows:print(row[0].value, row[1].value)# 获取所有列的数据(获取某一行的数据) for col in wb.worksheets[0].columns:print(col[1].value)# 读合并单元格 for row in wb.worksheets[1].rows:print(row)for item in sorted(wb.worksheets[1].merged_cells.ranges):if wb.worksheets[1].cell(1, 2).coordinate in item:print(item.start_cell.value)
2.写Excel
-
原文件基础上写内容
# 写Excel # 修改单元格数据 sheet = wb.worksheets[1] cell = sheet.cell(2, 4) cell.value = "生产产地" wb.save(os.path.join(os.environ['SystemDrive'], "/Users/梁/Desktop/测试修改.xlsx"))
-
新创建Excel文件写内容
from openpyxl import load_workbook, workbook from openpyxl.styles import Alignment, Border, Side, Font, PatternFill, GradientFill# 创建Excel且默认会创建一个sheet(名称为Sheet) wb = workbook.Workbook() # 或 sheet = wb["Sheet"] sheet = wb.worksheets[0] # 找到单元格,并修改单元格的内容 cell = sheet.cell(1, 1) cell.value = "测试参数"# 将Excel表保存到指定位置 wb.save(os.path.join(os.environ['SystemDrive'], "/Users/梁/Desktop/测试新表输入.xlsx"))''' insert_rows(idx, amount=1)- idx 插入位置的行索引,新的行被插入到这个行之前- amount 要插入的行数,默认值为1 insert_cols(idx, amount=1)- idx 插入位置的列索引,新的行被插入到这个列之前- amount 要插入的列数,默认值为1 delete_rows(idx, amount)- idx 要删除的第一行的索引- amount 要删除的行数,默认值为1 delete_cols(idx, amount)- idx 要删除的第一列的索引- amount 要删除的列数,默认值为1 '''# 添加2行 # sheet.insert_rows(2, amount=2) # 删除2行 # sheet.delete_rows(1, amount=2) # 删除2列 # sheet.delete_cols(1, amount=1) # 保存 wb.save(os.path.join(os.environ['SystemDrive'], "/Users/梁/Desktop/测试新表输入.xlsx"))# 修改sheet名称 wb.worksheets[0].title = "测试表格" wb.save(os.path.join(os.environ['SystemDrive'], "/Users/梁/Desktop/测试新表输入.xlsx"))# 创建sheet并设置sheet颜色 sheet = wb.create_sheet("工作计划", 0) sheet.sheet_properties.tabColor = "1072BA" wb.save(os.path.join(os.environ['SystemDrive'], "/Users/梁/Desktop/测试新表输入.xlsx"))# 设置默认打开的sheet wb.active = 1 wb.save(os.path.join(os.environ['SystemDrive'], "/Users/梁/Desktop/测试新表输入.xlsx"))# 拷贝sheet new_sheet = wb.copy_worksheet(wb["工作计划"]) new_sheet.title = "新的工作计划" wb.save(os.path.join(os.environ['SystemDrive'], "/Users/梁/Desktop/测试新表输入.xlsx"))# 删除sheet del wb["测试表格"] wb.save(os.path.join(os.environ['SystemDrive'], "/Users/梁/Desktop/测试新表输入.xlsx"))# 获取某些单元格,修改值 cell_list = wb.worksheets[0]["B2":"C3"] for row in cell_list:for cell in row:cell.value = "测试值"wb.save(os.path.join(os.environ['SystemDrive'], "/Users/梁/Desktop/测试新表输入.xlsx"))# 对齐方式 '''horizontal,水平方向对齐方式 general, left, center, fill, justify, centerContinuous, distributedvertical,垂直方向对齐方式 top, center, bottom, justify, distributedtext_rotation,旋转角度wrap_text,是否自动换行 ''' cell = wb.worksheets[0].cell(2, 2) cell.alignment = Alignment(horizontal="center", vertical="center", textRotation=45) wb.save(os.path.join(os.environ['SystemDrive'], "/Users/梁/Desktop/测试新表输入.xlsx"))# 边框 ''' side的style有一下这些- dashDot','dashDotDot', 'dashed','dotted','double','hair', 'medium', 'mediumDashDot', 'mediumDashDotDot','mediumDashed', 'slantDashDot', 'thick', 'thin' ''' cell = wb.worksheets[0].cell(2, 3) cell.border = Border(top=Side(style="thin", color="FF86C1"),bottom=Side(style="dashed", color="FFB6C1"),left=Side(style="dashed", color="FEB6C1"),right=Side(style="dashed", color="F86CC1"),# 对角线diagonal=Side(style="thin", color="48DF51"),# 对角线的方向# 左下 ~ 右上diagonalUp=True,# 左上~ 右下diagonalDown=True) wb.save(os.path.join(os.environ['SystemDrive'], "/Users/梁/Desktop/测试新表输入.xlsx"))# 字体 cell = wb.worksheets[0].cell(3, 2) cell.font = Font(name="微软雅黑", size=12, bold=True, color="EF23EE", underline="single") wb.save(os.path.join(os.environ['SystemDrive'], "/Users/梁/Desktop/测试新表输入.xlsx"))# 背景色 cell = wb.worksheets[0].cell(3, 3) cell.fill = PatternFill(start_color="EE86C1", end_color="FF86E2", fill_type="solid") wb.save(os.path.join(os.environ['SystemDrive'], "/Users/梁/Desktop/测试新表输入.xlsx"))# 渐变背景色 cell = wb.worksheets[0].cell(2, 2) cell.fill = GradientFill("linear", stop=("FFFFFF", "99CCFF", "000000")) wb.save(os.path.join(os.environ['SystemDrive'], "/Users/梁/Desktop/测试新表输入.xlsx"))# 宽高(索引从1开始) wb.worksheets[1].row_dimensions[1].height = 30 wb.worksheets[1].column_dimensions['B'].width = 40 wb.save(os.path.join(os.environ['SystemDrive'], "/Users/梁/Desktop/测试新表输入.xlsx"))# 合并单元格 wb.worksheets[1].merge_cells("B2:C5") wb.save(os.path.join(os.environ['SystemDrive'], "/Users/梁/Desktop/测试新表输入.xlsx"))# 取消合并单元格 wb.worksheets[1].unmerge_cells("B2:C5") wb.save(os.path.join(os.environ['SystemDrive'], "/Users/梁/Desktop/测试新表输入.xlsx"))# 写入公式 wb.worksheets[0]["D1"] = "合计" wb.worksheets[0]["D2"] = "=SUM(D3:D5)" wb.save(os.path.join(os.environ['SystemDrive'], "/Users/梁/Desktop/测试新表输入.xlsx"))# 移动 wb.worksheets[1]["E3"] = "总计" wb.worksheets[1]["E4"] = "=A2*B4" wb.worksheets[1]["E5"] = "=SUM(A2,C4)" # 将A2:E5范围的数据,向右移动10个单元格,向下移动1个单元格 wb.worksheets[1].move_range("A2:E5", cols=10, rows=1, translate=True) wb.save(os.path.join(os.environ['SystemDrive'], "/Users/梁/Desktop/测试新表输入.xlsx"))# 打印区域 wb.worksheets[1].print_area = "A2:E5" wb.save(os.path.join(os.environ['SystemDrive'], "/Users/梁/Desktop/测试新表输入.xlsx"))# 打印时,每个页面的固定表头 wb.worksheets[1].print_title_cols = "A:D" wb.worksheets[1].print_title_rows = "1:3" wb.save(os.path.join(os.environ['SystemDrive'], "/Users/梁/Desktop/测试新表输入.xlsx"))
6.压缩文件
- 见上文shutil
7.补充知识
1.深浅拷贝
1.浅拷贝
-
不可变类型,不拷贝
-
由于python内部优化机制,内存地址是相同的;对于不可变类型而言,以后修改值,会重新创建一份数据。不会影响原数据
-
import copystring = "Ailke"
print(id(string)) # 2674432039728cstr = copy.copy(string)
print(id(cstr)) # 2674432039728object_list = ["Ailke", "root", [45, 23]]
print(id(object_list)) # 2437294345408
print(id(object_list[2])) # 2437296306752copy_object_list = copy.copy(object_list)
print(id(copy_object_list)) # 2437296306496
print(id(copy_object_list[2])) # 2437296306752
-
可变类型,只拷贝第一层
object_list = ["Ailke", "root", [45, 23]] print(id(object_list)) # 2437294345408 print(id(object_list[2])) # 2437296306752copy_object_list = copy.copy(object_list) print(id(copy_object_list)) # 2437296306496 print(id(copy_object_list[2])) # 2437296306752
2.深拷贝
-
不可变类型,不拷贝
strs = "Ailke" print(id(strs)) # 1769370573616copy_strs = copy.deepcopy(strs) print(id(copy_strs)) # 1769370573616
-
特殊的元组
-
元组元素中无可变类型,不拷贝
tup_list = ("Ailke", "root",) print(id(tup_list)) # 2283265800896copy_tup_list = copy.deepcopy(tup_list) print(id(copy_tup_list)) # 2283265800896
-
元素中有可变类型,找到所有[ 可变类型 ]或[ 含有可变类型的元组 ] 均拷贝一份
tup_list = ("Ailke", "root", [11, [44, 55], (11, 22), (11, [], 22), 33]) copy_tup_list = copy.deepcopy(tup_list)print("分割线".center(30, "#")) print(id(tup_list)) # 2219888325184 print(id(copy_tup_list)) # 2219888318080print(id(tup_list[2])) # 2219886650944 print(id(copy_tup_list[2])) # 2219887055424print(id(tup_list[2][1])) # 2219886331968 print(id(copy_tup_list[2][1])) # 2219887012608print(id(tup_list[2][2])) # 2219886197568 print(id(copy_tup_list[2][2])) # 2219886197568print(id(tup_list[2][3])) # 2219888325504 print(id(copy_tup_list[2][3])) # 2219888318016
-
-
可变类型
-
找到所有层级的 [ 可变类型 ] 或[ 含有可变类型的元组 ] 均拷贝一份
tup_list = ("Ailke", "root", [11, [44, 55], (11, 22), (11, [], 22), 33]) copy_tup_list = copy.deepcopy(tup_list)print(id(tup_list[2][2])) # 2219886197568 print(id(copy_tup_list[2][2])) # 2219886197568print(id(tup_list[2][3])) # 2219888325504 print(id(copy_tup_list[2][3])) # 2219888318016
-