我的Python之旅第三天
一 编码操作
1 编码 enconde()
英文字符编码为"utf-8"时,一个字符占一个字节。
s1='abcdef' b1=s1.encode('utf-8') print(b1) 结果为:b'abcdef'
汉字编码为"utf-8"时,一个汉字占三个字节。
汉字编码为"gbk"时,一个汉字占两个字节。
s2='中国' b2=s2.encode('utf-8') b3=s2.encode('gbk') print(b2) print(b3)
结果为: b'\xe4\xb8\xad\xe5\x9b\xbd' b'\xd6\xd0\xb9\xfa'
2 解码 deconde()
s4="你好" b4=s4.encode('utf-8') b5=b4.decode('utf-8') print("'你好'编码为'utf-8'后为:",b4) print("解码后为:",b5) b6=s4.encode('gbk') b7=b6.decode('gbk') print("'你好'编码为'gbk'后为:",b6) print("解码后为:",b7)
结果为: '你好'编码为'utf-8'后为: b'\xe4\xbd\xa0\xe5\xa5\xbd' 解码后为: 你好 '你好'编码为'gbk'后为: b'\xc4\xe3\xba\xc3' 解码后为: 你好
二 深浅copy
定义:
在Python中对象的赋值其实就是对象的引用。当创建一个对象,把它赋值给另一个变量的时候,python并没有拷贝这个对象,只是拷贝了这个对象的引用而已。
浅拷贝:拷贝了最外围的对象本身,内部的元素都只是拷贝了一个引用而已。也就是,把对象复制一遍,但是该对象中引用的其他对象我不复制
深拷贝:外围和内部元素都进行了拷贝对象本身,而不是引用。也就是,把对象复制一遍,并且该对象中引用的其他对象我也复制。
1 浅copy
(1)浅copy 第一层各自独立,从第二层开始,共用一个内存地址。
s1=[1,2,3] s2=s1 print(s1,s2) s1.append(666) print(s1) print(s2) print(id(s1)) print(id(s2))
结果为:
[1, 2, 3] [1, 2, 3] [1, 2, 3, 666] [1, 2, 3, 666] 2670563612488 2670563612488
可以看到s1、s2的内存地址是一样的,既就是s2为s1的一个引用而已。
(2)
s3=[1,2,3,[44,55]] s4=s3.copy() s3[-1].append(666) print(s3) print(s4) print(id(s3[-1])) print(id(s4[-1]))
结果为:
[1, 2, 3, [44, 55, 666]] [1, 2, 3, [44, 55, 666]] 1781567379272 1781567379272
2深copy
import copy s5=[1,2,3,[44,55]] s6=copy.deepcopy(s5) s5.append(666) print(s5) print(s6) print(id(s5)) print(id(s6))
结果为:
[1, 2, 3, [44, 55], 666] [1, 2, 3, [44, 55]] 1774773104968 1774773106248
可以看到s5、s6的内存地址是不一样的。
对于深copy来说,两个是完全独立的,改变任意一个的元素(无论是多少层),另一个绝不会改变。
总结:
(1)深浅拷贝都是对源对象的复制,占用不同的内存空间。
(2)不可变类型的对象,对于深浅拷贝毫无影响,最终的地址值和值都是相等的。
(3)可变类型:
=浅拷贝: 值相等,地址相等
copy浅拷贝:值相等,地址不相等
deepcopy深拷贝:值相等,地址不相
三 文件操作
操作系统读写文件的一般流程:
(1)打开文件,产生文件句柄。
(2)对文件句柄进行操作。
(3)关闭文件句柄
文件句柄:
在文件I/O中,要从一个文件读取数据,应用程序首先要调用操作系统函数并传送文件名,并选一个到该文件的路径来打开文件。该函数取回一个顺序号,即文件句柄(file handle),该文件句柄对于打开的文件是唯一的识别依据。要从文件中读取一块数据,应用程序需要调用函数ReadFile,并将文件句柄在内存中的地址和要拷贝的字节数传送给操作系统。当完成任务后,再通过调用系统函数来关闭该文件。
1 读 r
(1)全部读出来read()
f1=open('log.txt',encoding='utf-8') content=f1.read() print(content) f1.close()
结果为:
abcde
fghigk
lmnopq
(2)读一部分 read(n)
f2=open('test.txt',encoding='utf-8') print(f2.read(3)) f2.close() 结果为:你好五
f3=open('test.txt','rb') print(f3.read(3).decode('utf-8')) f3.close() 结果为:你
说明:
r 模式 read(n) n 按照字符读取。
rb 模式 read(n) n 按照字节读取。
(3)按行读取 readline()
f4=open('test.txt',encoding='utf-8') print(f4.readline()) print(f4.readline()) f4.close() 结果为: 你好五月
第二行1abcdefghijklmnopqrstuvwxyz
(4)readlines() 读取所有行,并存入列表中
f5=open('test.txt',encoding='utf-8') print(f5.readlines()) f5.close() 结果为: ['你好五月\n', '第二行1abcdefghijklmnopqrstuvwxyz\n', '2345']
(5)for 循环逐行读取
f6=open('test.txt',encoding='utf-8') for line in f6: print(line) f6.close()
结果为:
你好五月
第二行1abcdefghijklmnopqrstuvwxyz
2345
(6)读写 r+ ,先读后写
f7=open('test.txt','r+',encoding='utf-8') print("原始文件为:",f7.read()) f7.write('aaaa') f7.seek(0) print("修改后文件为:",f7.read()) f7.close()
结果为:
原始文件为: 你好五月 第二行1abcdefghijklmnopqrstuvwxyz 2345 修改后文件为: 你好五月 第二行1abcdefghijklmnopqrstuvwxyz 2345aaaa
注意:
如果是Windows系统文件,加路径读取方式如下
f1=open(r'D:\Python\python\day03\test.txt',,encoding='utf-8')
2 写 w
(1)w 如没有文件,新建文件写入内容
有原文件,先清空内容,在写入新内容
f1=open('test2.txt','w',encoding='utf-8') f1.write('这个世界很疯狂') f1.close()
写入完毕,下来读取文件
f1=open('test2.txt',encoding='utf-8') print(f1.read()) f1.close()
结果为:这个世界很疯狂
(2)图片的读取及写入
原图如下
先来读取图片、目前读取二进制文件内容
p1=open('girl.jpg','rb') content = p1.read() print(content) p1.close()
结果为:b'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x01\x00H\x00H\x00\x00\xff\xdb\x00C\x00\x03\x02\x02\x02\x02\x02\x03\x02\x02\x02\x03\x03\x03\x03\x04\x06\x04\x04\x04\x04\x04\x08\x06\x06\x05\x06\t\x08\n\n\t\x08\t\t\n\x0c\x0f\x0c\n\x0b\x0e\x0b\t\t\r\x11\r\x0e\x0f\x10\x10\x11\x10\n\x0c\x12\x13\x12\x10\x13\x0f\x10\x10\x10\xff\xdb\x00C\x01\x03\x03\x03\x04\x03\x04\x08\x04\x04\x08\x10\x0b\t\x0b\x10\x10 \x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x………………….
写入,也是用二进制编码写入
p1=open('girl.jpg','rb') content = p1.read() print(content) p2 = open('girl2.jpg', 'wb') p2.write(content) p1.close() p2.close()
(3)w+先写后读
f2=open('log2.txt','w+',encoding='utf-8') f2.write('我在测试先写后读') f2.seek(0) print(f2.read()) f2.close() 结果为:我在测试先写后读
(4)a 没有文件则新建文件并写入,有的话直接追加
a:附加写方式打开,不可读
先追加
f3=open('log3.txt','a',encoding='utf-8') f3.write('今天是周一\n') f3.seek(0) f3.close()
在读取
f4=open('log3.txt',encoding='utf-8') print(f4.read()) f4.close() 结果为:今天是周一
(5)a+: 附加读写方式打开
f5=open('log4.txt','a+',encoding='utf-8',) f5.write('我在测试a+模式') f5.seek(0) print(f5.read()) f5.close() 结果为:我在测试a+模式
(6)其他操作方法
# readable 是否可读 # writable 是否可写 # f1.seek(12) # 任意调整 # f1.seek(0,2) #光标调整到最后 # f1.seek(0) #光标调整到开头 # f1.tell() # 告诉光标的位置 # f1.truncate(3) # 按照字节对原文件进行截取 必须在a 或 a+ 模式
(7)不用主动关闭文件句柄
with open('log.txt',encoding='utf-8') as f6: print(f6.read()) 结果为: abcde fghigk lmnopq rstuvwxy
当然也可一次操作多个文件
with open('log.txt',encoding='utf-8') as f6,\ open('log3.txt','a+',encoding='utf-8') as f7: print(f6.read()) f7.write('文件句柄测试') f7.seek(0) print(f7.read())
结果为:
abcde
fghigk
lmnopq
rstuvwxy
今天是周一
今天是周一
文件句柄测试
3 改
(1)以读模式打开原文件。
(2)以写的模式打开一个新文件。
(3)将原文件读出按照要求修改将修改后的内容写入新文件。
(4)删除原文件。
(5)将新文件重命名原文件。
import os with open('file', encoding='utf-8') as f1,\ open('file.bak', encoding='utf-8', mode='w') as f2: old_content = f1.read() new_content = old_content.replace('abc', 'hhh') f2.write(new_content) os.remove('file') os.rename('file.bak', 'file')
#升级版本
import os with open('file', encoding='utf-8') as f1,\ open('file.bak', encoding='utf-8', mode='w') as f2: for line in f1: new_line = line.replace('abc','hhh') f2.write(new_line) os.remove('file') os.rename('file.bak', 'file')
四 初识函数
1 函数的定义
(1)什么是函数
函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。
函数能提高应用的模块性,和代码的重复利用率。
你已经知道Python提供了许多内建函数,比如print()。
但你也可以自己创建函数,这被叫做用户自定义函数。
(2)定义函数:
def 关键字 函数名(): 函数体 函数执行:函数名() 函数:以功能为导向
s = 'asdgagsgadsgag' def my_len(): count = 0 for i in s: count += 1 print(count) print(my_len())
2 函数的终止与返回值
(1)终止函数。
(2)给函数的执行者返回值。
return 或者 return None
return 单个值
return 多个值 会将多个值放到一个元组中,将元组返回个函数的执行者
3 函数的传参
(1)认识实参、形参
def my_len(argv): # 形式参数 ,形参 count = 0 for i in argv: count += 1 return count s = 'lkfjsjulkjdgjdsf' l1 = [1, 2, 3, 4, 5] my_len(s) # 实际参数, 实参 print(my_len(l1))
-
实参角度
位置参数 按照顺序一一对应
关键字传参 一一对应
混合参数,(位置参数,关键字参数) 关键字参数必须在位置参数后面。
-
形参角度
位置参数,按顺序一一对应。
默认参数, 默认参数在位置参数的后面。
动态参数, *args, **kwargs 万能参数。
所有的位置参数,放在一个元组中。
所有的关键字参数,放在一个字典中。
-
形参的顺序
位置参数 *args, 默认参数,**kwargs