Python学习5

1.文件读写

(1)读文件
使用open()传入文件和标识符:

f = open('D:/Workspace/PycharmProjects/test/beread.txt', 'r')//标识符'r'表示读

//如果文件不存在,就会抛出IOError错误,如果打开成功,就可以用read()方法一次把文件的全部内容读到内存
f.read()

//最后需要调用close()关闭文件
f.close()

如果文件读写过程中产生IOError,后面的f.close()就不会调用,文件就无法关闭,解决这个问题的第一种方法是使用try...finally

try:
    f = open('/path/to/file', 'r')
    print f.read()
finally:
    if f:
        f.close()

这么写比较繁琐,所以Python引入了with语句来自动调用close方法:

with open('/path/to/file', 'r') as f:
     print f.read()

read()方法会一次性读取文件的全部内容,文件比较小时,这种读取方法最方便;如果不能确定文件大小,反复调用read(size)比较保险,size表示每次最多读取size个字节的内容;如果是配置文件,调用readlines()最方便:

for line in f.readlines():
    print(line.strip()) //去掉末尾的'ln'

(2)file-like Object
open()函数返回的这种有个read()方法的对象,在Python中统称为file-like Object。除了file外,还可以是内存的字节流,网络流,自定义流等等。file-like Object不要求从特定类继承,只要写个read()方法就行。

(3)读取二进制文件&非ASCII编码文件
前面讲的默认都是读取文本文件,并且是ASCII编码的文本文件。要读取二进制文件,比如图片,视频等等,要用标识符'rb'打开:

open('D:/Workspace/PycharmProjects/test/beread.jpg', 'rb')

如果要读非ASCII编码的文件,就必须以二进制模式打开,再解码。比如GBK编码的文件:

f = open('D:/Workspace/PycharmProjects/test/gbk.txt', 'rb')
u = f.read().decode('gbk')

这样子手动装换太麻烦,Python提供了一个codecs模块来在读文件时自动转换编码,直接读出unicode:

import codecs
with codecs.open('D:/Workspace/PycharmProjects/test/gbk.txt', 'r', 'gbk') as f:
    f.read()

(4)写文件
使用write()函数,方法和读文件类似,只是标识符要改为'w'或者'wb'

with open('/Users/michael/test.txt', 'w') as f:
    f.write('Hello, world!')

2.操作文件和目录
Python内置的os模块可以直接调用操作系统提供的接口函数。操作文件和睦的函数一部分放在os模块中,一部分放在os.path模块中:

os.path.abspath('.') //查看当前目录的绝对路径
D:\Workspace\PycharmProjects\test

#在该目录下创建一个新目录
#首先把新目录的完整路径表示出来
os.path.join('D:\Workspace\PycharmProjects\test', 'newcreate')
#然后创建一个新的目录:
os.mkdir('D:\Workspace\PycharmProjects\test\newcreate')
#删掉一个目录
os.rmdir('D:\Workspace\PycharmProjects\test\newcreate')

把两个路径合成一个时,不要直接拼字符串,而要通过os.path.join(),这样可以正确处理不同操作系统的分隔符,拆分时也是同样道理,要用os.path.split(),拆分后的后一部分总是最后级别的目录或文件名

os.path.split('D:\Workspace\PycharmProjects\test\newcreate')

('D:\Workspace\PycharmProjects\test','newcreate')

os.path.splitext()可以直接得到文件扩展名

os.path.splitext('/path/to/file.txt')
('/path/to/file', '.txt')

对当前目录下文件的操作:

os.rename('beread.txt', 'newname.py')//文件重命名

os.remove('beread.jpg')//删除文件

但是os模块中没有复制文件的函数,但在shutil模块中提供了copyfile()的函数,传入两个参数,第一个是被复制文件的名字,第二个是新文件的名字。

os.listdir('.')  # 列出当前目录的所有文件和子目录
os.path.isdir(x)  # 判断x是否为目录
os.path.isfile(x)  # 判断x是否为文件
os.walk('.') # 遍历当前目录的所有文件和子目录和子目录的文件,返回值去pycharn里面看

文件操作的一些方法:https://www.cnblogs.com/tkinter/p/5631213.html

3.序列化
①Python提供cPicklepickle两个模块来实现序列化,两个模块功能一样,只是前者是用c语言写的,速度快,所以导入的时候先尝试导入前者:

try:
    import cPickle as pickle
except ImportError:
    import pickle


d = dict(name = 'Bob', age = 20, score = 88)
pickle.dumps(d)

pickle.dumps()方法把任意对象序列化成一个str,然后就可以把这个str写入文件,或者用另一个方法pickle.dump()直接把对象序列化后写入一个file-like Object:

f = open('dump.txt', 'wb')
pickle.dum(d, f)
f.close()

#反序列化
f = open('dump.txt', 'rb')
d = pickle.load(f)
f.close()
print d
{'age': 20, 'score': 88, 'name': 'Bob'}

②JSON
如果我们要在不同的编程语言之间传递对象,就必须把对象序列化为标准格式,比如XML,但更好的方法是序列化为JSON,因为JSON表示出来就是一个字符串,可以被所有语言读取,也可以方便地存储到磁盘或者通过网络传输。JSON不仅是标准格式,并且比XML更快,而且可以直接在Web页面中读取,非常方便。
Python的json模块提供了转换方法:

import json
d = dict(name='Bob', age=20, score=88)
json.dumps(d) # dumps()方法返回一个内容为JSON标准的str

f = open('jsondump.txt', 'wb')
json.dump(d, f) # dump()方法把d转化为JSON后写入一个file-like Object.
f.close()

JSON同样有loads()load()的方法来进行反序列化,loads()把JSON类型的字符串反序列化,load()从file-like Object读取字符串并且反序列化,需要注意的是反序列化得到的所有字符串对象默认都是unicode而不是str

import json
f = open('dump.txt', 'rb')
d = json.load(f)
f.close()
print d
{u'age': 20, u'score': 88, u'name': u'Bob'}

③JSON进阶

class Student(object):
    def __init__(self, name, age, score):
        self.name = name
        self.age = age
        self.score = score

s = Student('Bob', 20, 88)
print(json.dumps(s))

当直接用dumps(d)序列化一个class对象d时会报错,因为class对象不是一个可序列化为JSON的对象,不过dumps()方法还有很多可选参数,可选参数default就是把任意一个对象变成一个可序列为JSON的对象,我们只需要为类对象写一个转换函数,再把函数传入:

def change(std):
    return {
    'name': std.name
    'age': std.age
    'score': std.score
    }

print(json.dumps(s, default = change))

另一种方法是通过class实例的__dict__属性,它就是一个dict,用来存储实例变量。也有少数例外,比如定义了__slots__class

print(json.dumps(s, default=lambda obj: obj.__dict__))

反序列化的时候,同样要写一个函数传入loads()object_hook,把dict对象转化了类的实例:

def changeback(d):
    return Student(d['name'], d['age'], d['score'])

json_str = '{"age": 20, "score": 88, "name": "Bob"}'
print(json.loads(json_str, object_hook = changeback))

4.正则表达式

①单子字符匹配
\d匹配一个数字,\w匹配一个字母或者数字,.匹配任意字符,\s匹配空格

②变长字符匹配
*表示任意个字符,包括0,
+表示至少一个字符,
?表示0个或者一个字符,
{n}表示n个字符,
{m,n}表示m到n个字符

'-'这样的特殊字符要用'\'转义

④进阶:
要做更精确的匹配,可以用[]表示范围,比如:
[0-9a-zA-Z\_]可以匹配一个数字、字母或者下划线;

[0-9a-zA-Z\_]+可以匹配至少由一个数字、字母或者下划线组成的字符串,比如'a100''0_Z''Py3000‘等等;

[a-zA-Z\_][0-9a-zA-Z\_]*可以匹配由字母或下划线开头,后接任意个由一个数字、字母或者下划线组成的字符串,也就是Python合法的变量;

[a-zA-Z\_][0-9a-zA-Z\_]{0, 19}更精确地限制了变量的长度是1-20个字符(前面1个字符+后面最多19个字符)。

A|B可以匹配A或B,所以(P|p)ython可以匹配'Python'或者'python'

^表示行的开头,^\d表示必须以数字开头。

$表示行的结束,\d$表示必须以数字结束。

⑤re模块
Python提供re模块,包含所有正则表达式的功能,匹配使尽量使用r'',这样就不需要转义:

import re
print re.match(r'\d{3}\s\-\s\d{3,8}', '010 - 12345')
<_sre.SRE_Match object at 0x0266EC28>
print re.match(r'\d{3}\-\d{3,8}', '010 - 12345')
None

如果match()匹配成功,则返回一个Match对象,否则返回None

⑥切分字符串
re.split(s)切分字符串比普通的`s.split(’ ‘)功能更强大,就算有连续的空格或者其他符号,都能切分出来:

re.split(r'[\s\,\;]+', 'a,b;; c  d')
['a', 'b', 'c', 'd']

⑦分组
除了简单地判断是否匹配之外,正则表达式还有提取子串的强大功能。用()表示的就是要提取的分组,比如^(\d{3})-(\d{3,8}$)就定义了两个组,可以直接从匹配的字符串中提取出区号和本地号码:

m = re.match(r'^(\d{3})-(\d{3,8})$', '010-12345')
print m.group(0) # group(0)永远是原始字符串
'010-12345'

print m.group(1), m.group(2) # group(1), group(2), ....表示第1、2、...个子串
'010' '12345'

print m.groups() # 打印出所有子串
('010', '12345')

⑧贪婪匹配
正则匹配默认是贪婪匹配,会尽可能多的匹配字符:

re.match(r'^(\d+)(0*)', '102300').groups()
('102300', '')

由于\d+采用贪婪匹配,所以会把整个字符串全部匹配掉,所以后面的0*只能匹配空字符串,要想\d+采用非贪婪匹配,在其后面加个?就可以:

re.match(r'^(\d+?)(0*)', '102300').groups()
('1023', '00')

⑨编译
当我们在Python中使用正则表达式时,re模块内部会干两件事情:

1.编译正则表达式,如果正则表达式的字符串本身不合法,会报错;

2.用编译后的正则表达式去匹配字符串。

如果一个正则表达式要重复使用几千次,出于效率的考虑,我们可以预编译该正则表达式,接下来重复使用时就不需要编译这个步骤了,直接匹配:

import re
re_pre = re.compile(r'^(\d{3})-(\d{3,8})$') #预编译
re_pre.match('010-12345').groups()
('010', '12345')
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值