Python正式课第十三天

2019-11-20  本文已影响0人  code与有荣焉

一、文件操作与字符编码

1. 字符编码

2. 字符编码的简单发展历史

它被设计为用1个字节来表示一个字符,所以ASCII码表最多只能表示2**8=256个字符实际上ASCII码表中只有128个字符,剩余的128个字符是预留扩展用的。

大家发现ASCII码预留的128个位置根本无法存储自己国家的文字和字符,因此各个国家开始制定各自的字符编码表

GBK一个中文相当于2个字节

Unicode规定所有的字符和符号最少由2个字节(16位)来表示,所以Unicode码可以表示的最少字符个数为2**16=65536。

由于Unicode规定每个字符最少占2个字节,美国不乐意了,因为ASCII码英文只占一个字节。

一个中文字符相当于3个字节
中文更占内存

3. 字符串和字节序列的转换

示例:

bytes = '张三'.encode()
print(bytes)  # b'\xe5\xbc\xa0\xe4\xb8\x89'
print(type(bytes))  # <class 'bytes'>
bytes = '张三'.encode('utf-8')
print(bytes)  # b'\xe5\xbc\xa0\xe4\xb8\x89'
print(type(bytes))  # <class 'bytes'>
bytes = '张三'.encode('gbk')
print(bytes)  # b'\xd5\xc5\xc8\xfd'
print(type(bytes))  # <class 'bytes'>

encode默认按utf-8编码

bytes = b'\xe5\xbc\xa0\xe4\xb8\x89'
msg1 = bytes.decode()
print(msg1)  # 张三
print(type(msg1))  # <class 'str'>

msg1 = bytes.decode('utf-8')
print(msg1)  # 张三
print(type(msg1))  # <class 'str'>

msg1 = bytes.decode('gbk')
print(msg1)  # 寮犱笁
print(type(msg1))  # <class 'str'>

encode()编码后,显示的是十六进制,但实际是2进制的。
1个字节可以表达两个十六进制

4. 文件概念

5. 文件的基本操作

函数/方法 说明
open 打开文件,并且返回文件操作对象
read 将文件内容读取到内存
write 将指定内容写入文件
close 关闭文件

读入内存可以理解为读进一个变量中

# 1\. 打开 - 文件名需要注意大小写
file = open("demo2.txt",encoding='utf-8')
print(file)
# 2\. 读取
text = file.read()
print(text)

# 3\. 关闭
file.close()

注意:

  1. 编码和解码的方式要相同,否则会乱码。
  2. pycharm默认utf-8编码
  3. Python默认是按照gbk(cp936)编码方式解码的
  4. 打开文件要记得关闭,忘记关闭文件,会造成系统资源消耗,而且会影响到后续对文件的访问
# 打开文件
f = open("abc.txt", "w",encoding='utf-8')
print(f)
f.write("hello neuedu!\n")
f.write("今天天气真好")

# 关闭文件
f.close()

open方法默认以读的方式打开

6. read()、readline()、readlines()区别与用法

read([size])方法从文件当前位置起读取size个字节,若无参数size,则表示读取至文件结束为止,它的返回值为字符串对象

f = open("a.txt")
lines = f.read()
print(lines)
print(type(lines))
f.close()

从字面意思可以看出,该方法每次读出一行内容,所以,读取时占用内存小,比较适合大文件,该方法返回一个字符串对象。

f = open("a.txt")
line = f.readline()
print(type(line))
while line:
 print(line)
 line = f.readline()
f.close()

读取整个文件所有行,保存在一个列表(list)变量中,每行作为一个元素,但读取大文件会比较占内存。

f = open("a.txt")
lines = f.readlines()
print(type(lines))
for line in lines:
 print(lines)
f.close()
f = open("a.txt")
for line in f:
 print(line)
f.close()

7. 使用 with open() as 读写文件

由于文件读写时都有可能产生IOError,一旦出错,后面的f.close()就不会调用。所以,为了保证无论是否出错都能正确地关闭文件,Python引入了with语句来自动帮我们调用close()方法

8.文件指针

文件指针 标记 从哪个位置开始读取数据

控制文件指针移动
方法:
f.seek(offset,whence) offset代表文件指针的偏移量,单位是字节bytes whence代表参照物,有三个取值
(1)0:参照文件的开头
(2)1:参照当前文件指针所在的位置
(3)2:参照文件末尾
注意:

  1. 其中whence=1和whence=2只能在b 模式下使用
  2. f.tell()函数可以得到当前文件指针的位置
  3. 指针是从0开始的,正向读,指针指向第0位置为空,反向读指针指向第0位置为最后一个数

9. 打开文件的方式总结

总结
读写图片等二进制文件用rb、rb+、wb、wb+、ab、ab+

二、文件操作练习

1.文件操作

1). 创建文件data.txt, 文件共100000行, 每行存放一个1~100之间的整数.
2). 找出文件中数字出现次数最多的10个数字, 写入文件mostNum.txt;

import random

f = open('data.txt', 'w+')
for i in range(100000):
    f.write(str(random.randint(1,100)) + '\n')
print(f.read())
f.close()
from collections import Counter
dict={}
f = open('data.txt', 'r+')
for i in f:
    if i not in dict:
        dict[i] = 1
    else:
        dict[i] = dict[i] + 1
d = Counter(dict)
with open('mostNum.txt', 'w+') as k:
    for i in d.most_common(10):
        k.write(f'{i[0].strip()}--------{i[1]}\n')
    k.seek(0, 0)
    print(k.read())
f.close()

2. 添加行号

1). 编写程序, 将a.txt操作生成文件a_num.txt文件,
2). 其中文件内容与a.txt一致, 但是在每行的行首加上行号。

with open('a.txt', 'r+') as f1, open('a_num.txt', 'w+') as f2:
    for i, j in enumerate(f1):
        f2.write(str(i)+'  '+j.strip()+'\n')
    f2.seek(0, 0)
    print(f2.read())

3. 非文本文件的读取

如果读取图片, 音乐或者视频(非文本文件), 需要通过二进制的方式进行读取与写入;b

f1 = open("a.png", mode='rb')
content = f1.read()
f1.close()
# print(content)

f2 = open('b.png', mode='wb')
f2.write(content)
f2.close()

三、模块与包

一个.py文件就称为一个模块

1. 方式一:import 模块名

使用时:模块名.函数名()

import module1
module1.output()
2. 方式二 :from 模块名 import 函数名

使用时:函数名()

from module1 import output
output()
3. 方式三: from 模块名 import *

使用时:函数名()

from module1 import *
output()

*表示所有

4. 方式四:from 模块名 import 函数名 as tt(自定义)

注意原来的函数名将失效
使用时:tt()

from module1 import output as tt
tt()

5. 可以在模块当中定义一个变量all,指定导出的函数子集:
使用all的影响: 后面的[]里面写什么函数名,使用from 模块名 import 方式导入时导入什么 all如果没有这个变量将全部导入(all仅限 于from 模块名 import 这种导入方式)

__all__=['output']
def output():
    print('hello neuedu')

def output2():
        print('hello output2')

包就是一个文件夹,里面包含了若干py文件以及一个_init_.py文件。

1. 方式一:from 包名 import 模块名

使用时:模块名.函数名()

from neuedu import module3
module3.output()
2. 方式二:from 包名.模块名 import 函数名

使用时:函数名()

from neuedu.module3 import output
output()
3. 方式三 :import 包名.模块名

使用的时候:包名.模块名.函数名()

import neuedu.module3
neuedu.module3.output()
4. 方式四:from 包名 import *

前提是:将 init.py 文件中写入all变量(写入方式同模块导入的写入方式) 。 变量当中写入哪个模块则导入哪个模块,不写则什么都不导入 使用时:模块名.函数名()
_init_.py

__all__ = ['module3']
from neuedu import *
module3.output()
5. 方式五:import 包名

前提是:在包里面的init.py 文件里写入 from . import 模块名 init.py里面导入哪个模块 通过本方式就能使用哪个模块
使用时:包名.模块名.函数名()
_init_.py

from . import module3
import neuedu
neuedu.module3.output()
上一篇下一篇

猜你喜欢

热点阅读