Python语法笔记3

1、正则表达式

在re模块中实现

import re
s = r’abc’
print re.findall(s, ‘ababcdbabcbc’) #[‘abc’, ‘abc’]
s = r’t[io]p’
print re.findall(s,’top tiop abc tip’) #[‘top’, ‘tiop’, ‘tip’] 包含
s = r’t[^io]
p’
print re.findall(s,’top tiop tabcp tip’) #[‘tabcp’] 排除

1.1、元字符:

[]

指定一个字符集:[abc], [a-z]

元字符在字符集中不起作用[sjdkf$],只会当做普通字符处理(^表示除了,而不是匹配行首)

^

匹配行首,除非设置MULTILINE标志,它只是匹配字符串的开始。在MULTILINE模式里,它也可以直接匹配字符串中的每个换行。

$

匹配行尾,行尾被定义为要么是字符串尾,要么是一个换行字符后面的任何位置

1.2、元字符与转义字符

import re
r = r’\^abc’ #使用\^匹配尖括号
print re.findall(r, ‘^abc’); #[‘^abc’]

反斜杠后面可以加不同的字符以表示不同特殊意义

也可以用于取消所有的元字符: \[ \\

转义字符

含义

\d

任何的十进制数字 [0-9]

\D

任何非数字字符 [^0-9

\s

任何空白字符 [\t\n\r\f\v]

\S

任何非空白字符 [^\t\n\r\f\v]

\w

任何字母数字字符 [a-zA-Z0-9_]

\W

任何非字母数字字符 [^a-zA-Z0-9_]

*

指定前一个字符可以被匹配零次或者多次

import re
r = r’^010-[0-9]*’
print re.findall(r, ‘010-12345678’); #[‘010-12345678’]
r = r’^010-[0-9]{8}’
print re.findall(r, ‘010-1234567890’); #[‘010-12345678’]

+

表示匹配一次或多次

?

匹配一次或零次,用于标示某事物是可选的

import re
r = r’^010-?[0-9]{8}$’
print re.findall(r, ‘0101235678’); #[‘01012345678’]

  • 最大匹配(贪婪模式)
  • 最小匹配(非贪婪模式)

import re
r = r’ab+’
print re.findall(r, ‘abbbbbbbbbb’); #[‘abbbbbbbbbb’] #最大匹配
r = r’ab?’
print re.findall(r, ‘abbbbbbbbbb’); #[‘ab’] #最小匹配

{m,n}

至少有m个重复,最多有n个重复

import re
r = r’ab{2,}’
print re.findall(r, ‘abbbbbb’) #[‘abbbbbb’]

表达式

含义

{0,}

等同于 *

{1,}

等同于 +

{0,1}

等同于?

1.3、如何在Python中使用正则表达式:

re模块提供了一个正则表达式引擎的接口,可以将REstring编译成对象并用他们来进行匹配。

import re
p = re.compile(‘ab’) #编译成对象,解释起来比较快
print p #<_sre.SRE_Pattern object at 0x0044ED40>
print p.findall(‘aaaabbb’) #[‘ab’]
p = re.compile(‘ab’, re.I) #不区分大小写
print p.findall(‘Ab’) #[‘Ab’]

反斜杠的麻烦:

  • 字符串前加r,反斜杠就不会被任何特殊方法处理

import re
p = r’\sb’
print re.findall(p, ‘\sb’) #[]
p = r’\\sb’
print re.findall(p, ‘\\sb’) #[‘\\sb’]
p = ‘\\\sb’
print re.findall(p, ‘\sb’) #[‘\\sb’]
p = re.compile(‘\\\sb’);
print p.findall(‘\sb’); #[‘\\sb’]

1.4、执行匹配:

RegexObject实例有一些方法和属性:

  • match(): 决定RE是否在字符串刚开始的位置匹配
  • search(): 扫描字符串,找到这个RE匹配的位置
  • findall(): 找到RE匹配的所有子串,作为列表返回
  • finditer(): 找到RE匹配的所有子串,作为迭代器返回

import re
p = re.compile(‘ab’)
print p.match(‘cab’) #None
print p.search(‘cab’) #<_sre.SRE_Match object at 0x01DFBB10>
print p.finditer(‘cababb’) #
x = p.finditer(‘cababb’)
print x.next() #<_sre.SRE_Match object at 0x003FBB10>

上面迭代器next()方法返回了一个Match,关于该对象的相关方法:

  • group(): 返回被RE匹配的字符串
  • start(): 返回匹配开始的位置
  • end(): 返回匹配结束的位置
  • span(): 返回一个元祖包含匹配(开始,结束)的位置

import re
p = re.compile(‘ab’)
m = p.search(‘cababb’) #
if m:
print m.group(0) #ab

1.5、模块级函数:

re模块也提供了顶级函数调用如:

  • match()
  • search()
  • sub()
  • subn()
  • split()
  • findall()

使用上面的方法,可以使用正则替换或者切割查找匹配字符串

import re
p = re.compile(‘ab’)
print re.sub(p, ‘‘, ‘sfabkjkbskbabaf’, 1) #sfkjkbskbabaf sub替换
print re.split(p, ‘abjkjkabjlkbaabjlj’) #[‘’, ‘jkjk’, ‘jlkba’, ‘jlj’]

Python常用的help小技巧:

print dir(re) #查看模块下的属性和方法

help(re.sub) #查看模块下的方法的介绍

1.6、编译标志:

标志

作用

DOTALL, S

使匹配包括换行在内的所有字符

IGNORECASE, I

使匹配对大小写不敏感

LOCALE, L

做本地化识别(locale-aware)匹配法语等特殊字符

MULTILINE, M

多行匹配,影响^和$

VERBOSE, X

能够使用REs的verbose状态,使之被组织得更清晰易懂

import re
r1 = r’itzhai.com’
print re.findall(r1, ‘itzhai.com’) #[‘itzhai.com’]
print re.findall(r1, ‘itzhai-com’) #[‘itzhai-com’]
print re.findall(r1, ‘itzhai\ncom’) #[]
print re.findall(r1, ‘itzhai\ncom’, re.S) #[‘itzhai\ncom’]

#多行
str = “””abskdfjaks
abkjaslkfa
abkjskfa
“””
r2 = r’^ab.*’
print re.findall(r2, str, re.M) #[‘abskdfjaks’, ‘abkjaslkfa’, ‘abkjskfa’]

#verbose状态
r3 = r”””
\d{3}
-?
\d{8}
“””
print re.findall(r3, ‘010-12345678’, re.X) #[‘010-12345678’]

1.7、分组:

使用括号进行分组

import re
email = r’\w{3,}@\w+(\.com|\.cn)’
print re.match(email, 'admin@itzhai.com‘) #<_sre.SRE_Match object at 0x02554D60>
m = re.match(email, 'admin@itzhai.com‘)
print m.group(0) + “, “ + m.group(1) #admin@itzhai.com, .com

#匹配的时候,会优先的返回分组中的数据:
print re.findall(email, 'admin@itzhai.com‘) #[‘.com’]

1.8、一个爬取程序

下面演示一个爬取并下载页面所有图片的例子:

import re
import urllib
def getHtml(url):
page = urllib.urlopen(url)
html = page.read()
return html
def getImg(html):
p = r’src=”(.*?\.jpg-itzhai)”‘
imgp = re.compile(p)
imgList = re.findall(imgp, html);
index = 0
for url in imgList:
urllib.urlretrieve(url, ‘%d.jpg’ % index)
index+=1
getImg(getHtml(“http://www.csdn.net/"))

2、Python对内存的使用

2.1、浅拷贝和深拷贝

浅拷贝:对引用的拷贝

深拷贝:对对象资源的拷贝

下面演示一下数组的复制和浅拷贝:

import copy

#下面演示下两个变量指向了同一个地址空间
a = [1, 2, 3, ‘test’]
b = a
print id(a) #39511344
print id(b) #39511344
a.append(‘hello’)
print a #[1, 2, 3, ‘test’, ‘hello’]
print b #[1, 2, 3, ‘test’, ‘hello’]
a.append([1,2]);
c = copy.copy(a)

#下面使用copy的复制方法复制数组,这样对a的操作就不会影响到c了
print id(a) #39513104
print id(c) #39515600
a[5][0] = ‘new’
print a #[1, 2, 3, ‘test’, ‘hello’, [‘new’, 2]]
print c [1, 2, 3, ‘test’, ‘hello’, [‘new’, 2]]

发现a改变了其中一个列表元素的里面的元组,c的元素也改变了,这就是浅拷贝的原因,内层的数据还是引用了同一个内存块

下面实现深拷贝:

import copy

#下面演示下两个变量指向了同一个地址空间
a = [1, 2, 3, ‘test’]
a.append(‘hello’)
a.append([1,2]);
d = copy.deepcopy(a)

#下面使用copy的复制方法复制数组,这样对a的操作就不会影响到c了
print id(a) #39644176
print id(d) #39648992
a[5][0] = ‘new’
print a #[1, 2, 3, ‘test’, ‘hello’, [‘new’, 2]]
print d #[1, 2, 3, ‘test’, ‘hello’, [1, 2]]

3、文件与目录

3.1、读写文件

Python进行文件读写的函数是open或file

file_handler = open(filename, mode)

两种读文件的方法

file1 = open(‘test.txt’)
print file1.read()
file1.close()
file2 = file(‘test.txt’)
print file2.read()
file2.close()

mode

作用

r

只读

r+

读写

w

写入,先删除原文件,再重新写入,如果文件没有则创建

w+

读写,先删除原文件,再重新写入,如果文件没有则创建(可以写入输出)

a

写入:在文件末尾追加新的内容,文件不存在,创建之

a+

读写,在文件末尾追加新的内容,文件不存在,创建之

b

打开二进制的文件,可以与r, w, a, + 结合使用

U

支持所有的换行符号,’r’, ‘\n’, ‘\r\n’

#写文件
file3 = open(‘test.txt’, ‘w’)
file3.write(‘last commit…’) #last commit…
file3.close()
file3 = open(‘test.txt’)
print file3.read()
file3.close();
file4 = open(‘test.txt’, ‘r+’)
file4.write(‘a’)
file4.close()
file4 = open(‘test.txt’, ‘r’) #关掉之后重新打开,使得文件指针复位,从头读取
print file4.read() #aast commit…
file4.close()

3.2、文件对象方法

FileObject.close()
String = FileObject.readline([size]) size: 前n个字符
List = FileObject.readlines([size])
String = FileObject.read([size])
FileObject.next()
FileObject.write(string)
FileObject.writelines(List)
FileObject.seek(偏移量, 选项)
选项:0 表示将文件指针指向从文件头部到“偏移量”字节处
1 表示将文件指针指向从文件的当前位置,向后移动“偏移量”字节处
2 表示将文件指针指向从文件的结尾,向前移动“偏移量”字节处
FileObject.flush()

#写文件
file1 = open(‘test.txt’)
for i in file1:
print i

3、OS模块

3.1、目录操作:

目录操作就是通过python来实现目录的创建,修改,遍历等功能

import os

目录操作需要调用os模块

比如

os.mkdir(‘text2.txt’)

其他方法:

mkdir(path[,mode=0777])
makedirs(name, mode=511) #级联添加
rmdir(path)
removedirs(path) #级联删除
listdir(path) #返回当前目录的所有文件,列表形式返回

os.listdir(‘.’)
os.listdir(‘/‘)

getcwd() #获得当前的路径

chdir(path) #切换目录

walk(top, topdown=True, onerror=None)

3.2、目录遍历

3.2.1、递归函数

import os
def listAllFiles(path):
files = os.listdir(path)
allfiles = []
for filename in files:
filepath = os.path.join(path, filename)
if os.path.isdir(filepath):
allfiles.append(listAllFiles(filepath))
allfiles.append(filepath)
return allfiles
print listAllFiles(‘/dev/workspace’);

3.2.1、os.walk()函数

generator = os.walk(‘/dev/workspace’)
for path, dirs, files in generator:
for filename in files:
print os.path.join(path, filename)

4、异常处理

try:
f = open(‘a.txt’, ‘r’)
print asdf
except IOError, e:
print False, str(e) #False [Errno 2] No such file or directory: ‘a.txt’
except NameError, e:
print False, str(e)
print ‘使用了不存在的变量’
finally:
if f:
f.close() #NameError: name ‘f’ is not defined 注意,如果这里不做判断或捕获NameError,由于文件没有打开成功,所以提示f未定义

4.1、抛出机制

如果在运行时发生异常,解释器就会查找到相应的处理语句;如果在当前函数里没有找到,则上层继续抛出,跟Java中的异常有点类型;如果在最外层(全局main)没有找到,解释器就会退出,同事打印traceback以便让用户找出错误产生的原因。

有时候异常不一定代表错误,有时候是一个警告,有时候也可能是一个终止信号,比如退出循环等。

4.2、raise抛出异常

使用raise来抛出异常:

raise TypeError(“‘a’必须为整型”);

异常

描述

AssertionError

assert语句失败

AttributeError

试图访问一个对象没有的属性

IOError

输入输出异常

ImportError

无法引入模块或者包

IndentationError

语法错误

IndexError

下标索引超出序列边界

KeyError

试图访问字典里不存在的key

KeyboardInterrupt

按下Ctrl+C时触发

NameError

使用一个还未赋予对象的变量

SyntaxError

Python代码逻辑语法出错,不能执行

TypeError

传入的对象类型与要求不符合

UnboundLocalError

试图访问一个还未设置的全局变量

ValueError

传入一个不被期望的值,类型不正确

arthinking wechat
欢迎关注itzhai公众号
  • 本文作者: arthinking
  • 本文链接: python-yu-fa-bi-ji-2.html
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!