Python基础知识总结


第 1 章  起步

1.1  #!/usr/bin/python3的理解

1. 这句话仅在linux或Unix系统下有作用,在Windows下无论在代码里加什么都无法直接运行一个文件名后缀为.py的脚本,因为在Windows下文件名对文件的打开方式起了决定性作用
2. 如果调用python脚本时,使用: python script.py。#!/usr/bin/python3会被忽略,等同于注释
3. 如果调用python脚本时,使用: ./script.py。#!/usr/bin/python3指定解释器的路径

1.2  python3基础语法

1.  编码
默认情况下,python3源文件以UTF-8编码,所有字符串都是Unicode字符串。当然也可以为源文件指定不同的编码:

# -*- coding: cp-1252 -*-

2.  标识符
·  第一个字符必须是字母或者下划线
·  标识符的其他部分由字母、数字、下划线组成
·  标识符对大小写敏感

3.  python保留字

import keyword
keyword.kwlist
['False', 'None', 'True', 'and', 'as', 'assert', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally','for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while','with', 'yield']

4.  多行语句

python通常是一行写完一条语句,但如果语句很长,我们可以使用反斜杠(\)来实现多行语句:

total = item_one + \
        item_two + \
        item_three

在[]、{}或()中的多行语句,不需要反斜杠(\):

total = ['item_one', 'item_two',
         'item_three']

5.  字符串

·  python中单引号和双引号使用完全相同
·  使用三引号('''或""")可以指定一个多行字符串
·  转移字符'\'
·  反斜杠可以用来转义,使用r可以使反斜杠不发生转义:

print('\'s.t.\'')
# 's.t.'
print(r'\'s.t.\'')
# \'s.t.\'

·  按字面意义级联字符串: 'this ''is ''a ''dog'会被自动转换成'this is a dog'
·  字符串可以用 + 运算符连接在一起,用 * 运算符重复:

print('love' + ' sports')
# love sports
print('love' * 3)
# lovelovelove

·  python中的字符串有两种索引方式,从左往右以0开始,从右往左以-1开始
·  python中的字符串不能被改变
·  python没有单独的字符类型,一个字符就是长度为1的字符串
·  python中的字符串切片语法格式如下: 变量[头下标:尾下标:步长]

6.  import与from...import

·  将整个模块导入: import amodule

·  将某个模块导入某个函数(类): from amodule import afunction
·  将某个模块导入多个函数(类): from amodule import firstfunction, secondfunction, thirdfunction
·  将某个模块导入全部函数(类): from amodule import *

7.  print函数sep参数的使用

a, b, c = 1, 2, 3
print(a, b, c)
# 1 2 3
print(a, b, c, sep='-_-')
# 1-_-2-_-3

第 2 章  变量和简单数据类型

2.1  基本数据类型

1.  多个变量赋值方式

·  a = b = c = 1
·  a, b, c = 1, 1.2, 'cat'

2.  标准数据类型:

Number(数字)、String(字符串)、List(列表)、Tuple(元组)、Sets(集合)、DicDictionary(字典)

3.  Number(int、float、bool、complex(复数))

type和isinstance:

a, b, c, d = 73, 7.3, False, 7 + 3j
print(type(a), type(b), type(c), type(d)
# <class 'int'> <class 'float'> <class 'bool'> <class 'complex'>
a = 73
isinstance(a, int)
# True

区别:

class A:
    pass
class B(A):
    pass
isinstance(A(), A)
# True
type(A()) == A
#True
isinstance(B(), A)
# True
type(B()) == A
# False

·  type()不会认为子类是一种父类型
·  isinstance()会认为子类是一种父类型

4.  在 Python2 中是没有布尔型的,它用数字 0 表示 False,用 1 表示 True。到 Python3 中,把 True 和 False 定义成关键字了,但它们的值还是 1 和 0,它们可以和数字相加。

5.  Python 字符串不能被改变。向一个索引位置赋值会导致错误。

6.  List(列表)中元素的类型可以不相同,它支持数字,字符串,也可以包含列表

7.  空元组: tuple1 = ()    含一个元素的元组: tuple2 = (73,)

8.  string、list、tuple都属于sequence

9.  set(集合)是一个无序不重复的序列。可以使用{}或set()函数创建集合。创建一个空集合时必须用set()而不是{},因为{}是用来创建一个空字典

a = set('abracadabra')
print(a)
# {'a', 'r', 'b', 'd', 'c'}
b = set('alacazam')
print(b)
# {'z', 'm', 'a', 'l', 'c'}
# a和b的差集
print(a - b)
# {'d', 'r', 'b'}
# a和b的并集
print(a | b)
# {'z', 'm', 'a', 'r', 'b', 'l', 'd', 'c'}
# a和b的交集
print(a & b)
# {'c', 'a'}
# a和b中不同时存在的元素
print(a ^ b)
{'z', 'm', 'b', 'l', 'r', 'd'}
# 集合的推导式
{x for x in 'abracadabra' if x not in 'ab'}    # {'d', 'c', 'r'}

10.  dictionary的几种构造方法

dict_1 = dict([('Cat', 1), ('Dog', 2), ('Bird', 3)])    # dict()中传入一个元组列表
print(dict_1)
# {'Cat': 1, 'Dog': 2, 'Bird': 3}
dict_2 = {x: x ** 2 for x in (2, 4, 6)}
print(dict_2)
# {2: 4, 4: 16, 6: 36}
dict_3 = dict(Cat=1, DOg=2, Bird=3)    # dict()中传入键值对的形式
# {'Cat': 1, 'Dog': 2, 'Bird': 3}

2.2  Number

python支持三种不同的数值类型:

·  整型(int): python3整型是没有限制大小的,可以当做long类型使用,所以python3没有python2的long类型

·  浮点型(float): 由整数部分和小数部分组成
·  复数(complex): 由实数部分和虚数部分构成,可以用a + bj,或者complex(a, b)表示,其中a,b都是浮点型

python数字类型转换:

  int(x)   将x转化为一个整数
  float(x)   将x转换为一个浮点数
  complex(x)   将x转换为一个复数,实数部分为x,虚数部分为0
  complex(x, y)   将x和y转换为一个复数,实数部分为x,虚数部分为y。
  python 不支持复数转换为整数或浮点数

float(7 + 3j)
# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
# TypeError: can't convert complex to float

数学函数:

# 返回数字的绝对值
abs(-73)    # 73
import math
# 向上取整
math.ceil(7.3)    # 8
# 返回e的x次幂
math.exp(1)    # 2.718281828459045
# 返回数字的绝对值(返回的是一个浮点数)
math.fabs(-73)    # 73.0
# 向下取整
math.floor(7.3)    # 7
# log(x)
math.log(math.e)    # 1.0
math.log(100, 10)    # 2.0
# log10(x)
math.log10(100)    # 2.0
# max(x1, x2, ...)
max(1, 9, 9, 5, 7, 3)    # 9
# min(x1, x2, ...)
min(1, 9, 9, 5, 7, 3)    # 1
# modf(x)返回浮点数的小数部分和整数部分
math.modf(7.3)    # (0.2999999999999998, 7.0)
# pow(x, y) ——> x ** y
pow(7, 3)    # 343
# sqrt(x)取平方根
math.sqrt(9)    # 3.0
# round(x[, n])返回浮点数x的四舍五入值,如给出n值,保留小数点n位
round(7.3)    # 7
round(7.31995, 1)    # 7.3
# 奇进偶弃
round(10.5)    # 10
round(11.5)    # 12

随机数函数:

import random
# 从序列的元素中随机挑选一个
random.choice(range(10))    # 3
# 从指定范围内,按指定基数递增的集合中获取一个随机数,基数缺省为1
# 从0-9内随机选取一个数
random.randrange(10)    # 3
# 从1-20内随机选取一个基数
random.randrange(1, 20, 2)    # 11
# 随机生成下一个实数,它在[0, 1)范围内
random.random()    # 0.44951096884680863
# 将序列的所有元素随机排序
lst = [1, 9, 9, 5, 7, 3]
random.shuffle(lst)
print(lst)    # [3, 1, 7, 9, 9, 5]
# 随机生成下一个实数,它在[x, y]范围内
random.uniform(3, 7)    # 5.764023427644599
# 随机生成下一个整数
random.randint(73, 1995)    # 507
# 随机生成一个序列中的n数,返回一个列表
random.sample('she loves cats', 7)    # [' ', 'h', 'e', 's', 'v', 'o', 's']
random.sample([1, 2, 3, 4, 5, 6, 7], 3)    # [4, 2, 3]
random.sample((1, 2, 3, 4, 5, 6, 7), 3)    # [6, 3, 1]

2.3  字符串

· capitalize()
将字符串的第一个字符转换为大写
· center(width, fillchar)
返回一个指定的宽度 width 居中的字符串,fillchar 为填充的字符,默认为空格。
· count(str, beg= 0,end=len(string))
返回 str 在 string 里面出现的次数,如果 beg 或者 end 指定则返回指定范围内 str 出现的次数
· bytes.decode(encoding="utf-8", errors="strict")
Python3 中没有 decode 方法,但我们可以使用 bytes 对象的 decode() 方法来解码给定的 bytes 对象,这个 bytes 对象可以由 str.encode() 来编码返回。
· encode(encoding='UTF-8',errors='strict')
以 encoding 指定的编码格式编码字符串,如果出错默认报一个ValueError 的异常,除非 errors 指定的是'ignore'或者'replace'
· endswith(suffix, beg=0, end=len(string))
检查字符串是否以 obj 结束,如果beg 或者 end 指定则检查指定的范围内是否以 obj 结束,如果是,返回 True,否则返回 False.
· expandtabs(tabsize=8)
把字符串 string 中的 tab 符号转为空格,tab 符号默认的空格数是 8 。
· find(str, beg=0 end=len(string))
检测 str 是否包含在字符串中,如果指定范围 beg 和 end ,则检查是否包含在指定范围内,如果包含返回开始的索引值,否则返回-1
· index(str, beg=0, end=len(string))
跟find()方法一样,只不过如果str不在字符串中会报一个异常.
· isalnum()
如果字符串至少有一个字符并且所有字符都是字母或数字则返 回 True,否则返回 False
· isalpha()
如果字符串至少有一个字符并且所有字符都是字母则返回 True, 否则返回 False
· isdigit()
如果字符串只包含数字则返回 True 否则返回 False..
· islower()
如果字符串中包含至少一个区分大小写的字符,并且所有这些(区分大小写的)字符都是小写,则返回 True,否则返回 False
· isnumeric()
如果字符串中只包含数字字符(包含中文的‘一’‘二’‘三’‘壹’‘贰’‘百’‘千’‘万’等),则返回 True,否则返回 False
· isspace()
如果字符串中只包含空白,则返回 True,否则返回 False.
· istitle()
如果字符串是标题化的(见 title())则返回 True,否则返回 False
· isupper()
如果字符串中包含至少一个区分大小写的字符,并且所有这些(区分大小写的)字符都是大写,则返回 True,否则返回 False
· join(seq)

以指定字符串作为分隔符,将 seq 中所有的元素(的字符串表示)合并为一个新的字符串

str = ' '
str_tuple = ('she', 'loves', 'cat')
str.join(str_tuple)
# she loves cat
· len(string)
返回字符串长度
· ljust(width[, fillchar])
返回一个原字符串左对齐,并使用 fillchar 填充至长度 width 的新字符串,fillchar 默认为空格。
· lower()
转换字符串中所有大写字符为小写.
· lstrip()
截掉字符串左边的空格或指定字符。
· maketrans()    (与translate()共同使用)

创建字符映射的转换表,对于接受两个参数的最简单的调用方式,第一个参数是字符串,表示需要转换的字符,第二个参数也是字符串表示转换的目标。

intab = 'aeiou'
outtab = '12345'
str = 'this is a string example...'
# 制作翻译表
transtab = str.maketrans(intab, outtab)
str.translate(transtab)
# 'th3s 3s 1 str3ng 2x1mpl2...'
· max(str)
返回字符串 str 中最大的字母。
· min(str)
返回字符串 str 中最小的字母。
· replace(old, new [, max])
把 将字符串中的 str1 替换成 str2,如果 max 指定,则替换不超过 max 次。
· rfind(str, beg=0,end=len(string))
类似于 find()函数,不过是从右边开始查找.
· rindex( str, beg=0, end=len(string))
类似于 index(),不过是从右边开始.
· rjust(width,[, fillchar])
返回一个原字符串右对齐,并使用fillchar(默认空格)填充至长度 width 的新字符串
· rstrip()
删除字符串字符串末尾的空格.
· split(str="", num=string.count(str))
num=string.count(str)) 以 str 为分隔符截取字符串,如果 num 有指定值,则仅截取 num 个子字符串
· splitlines([keepends])

按照行('\r', '\r\n', \n')分隔,返回一个包含各行作为元素的列表,如果参数 keepends 为 False,不包含换行符,如果为 True,则保留换行符。

'ab c\n\nde fg\rkl\r\n'.splitlines(True)
# ['ab c\n', '\n', 'de fg\r', 'kl\r\n']
'ab c\n\nde fg\rkl\r\n'.splitlines(False)
# ['ab c', '', 'de fg', 'kl']
· startswith(str, beg=0,end=len(string))
检查字符串是否是以 obj 开头,是则返回 True,否则返回 False。如果beg 和 end 指定值,则在指定范围内检查。
· strip([chars])
在字符串上执行 lstrip()和 rstrip()
· swapcase()
将字符串中大写转换为小写,小写转换为大写
· title()
返回"标题化"的字符串,就是说所有单词都是以大写开始,其余字母均为小写(见 istitle())
· translate(table, deletechars="")

根据 str 给出的表(包含 256 个字符)转换 string 的字符, 要过滤掉的字符放deletechars 参数中
· upper()
转换字符串中的小写字母为大写
· zfill (width)
返回长度为 width 的字符串,原字符串右对齐,前面填充0
· isdecimal()
检查字符串是否只包含十进制字符,如果是返回 true,否则返回 false。

2.4  List

· len(list)
列表元素个数
· max(list)
返回列表元素最大值
· min(list)
返回列表元素最小值
· list(seq)
将序列转换为列表

· list.append(obj)    相当于a[len(a):] = [obj]
在列表末尾添加新的对象
· list.count(obj)
统计某个元素在列表中出现的次数
· list.extend(seq)    相当于a[len(a):] = [seq]
在列表末尾一次性追加另一个序列中的多个值(用新列表扩展原来的列表)
· list.index(obj)
从列表中找出某个值第一个匹配项的索引位置
· list.insert(index, obj)
将对象插入列表
· list.pop()
移除列表中的一个元素(默认最后一个元素),并且返回该元素的值
· list.remove(obj)
移除列表中某个值的第一个匹配项,如果没有就返回一个错误
· list.reverse()
反向列表中元素
· list.sort()
对原列表进行排序
· list.clear()    相当于del a[:]
清空列表
· list.copy()    相当于a[:]

复制列表

# 把列表当堆栈使用
stack = [3, 4, 5]
stack.append(6)
stack.append(7)
print(stack)    # [3, 4, 5, 6, 7]
stack.pop()    # 7
print(stack)    # [3, 4, 5, 6]
stack.pop()    # 6
stack.pop()    # 5
print(stack)    # [3, 4]

# 把列表当队列使用
from collections import deque
queue = deque(["Eric", "John", "Michael"])
queue.append("Terry")
queue.append("Graham")
queue.popleft()    # 'Eric'
queue.popleft()    # 'John'
print(queue)    # deque(['Michael', 'Terry', 'Graham'])
# 列表推导式(列表解析)
[x * 2 for x in (2, 4, 6)]    # [4, 8 ,12]
[(x, x ** 2) for x in (2, 4, 6)]    # [(2, 4), (4, 16), (6, 36)]
[str.strip() for str in ('  she', ' loves ', 'cat  ')]    # ['she', 'loves', 'cat']
# 用if做过滤器
[3 * x for x in (2, 4, 6, 16, 36) if x > 3]    # [12, 18, 48, 108]
[3 * x for x in (2, 4, 6, 16, 36) if x > 37]    # []
# 勾股定理构造列表
import math
[round(math.sqrt(x ** 2 + y ** 2), 1) for x in (3, 5) for y in (4, 12)]    # [5.0, 12.4, 6.4, 13.0]
[str(round(math.pi, i)) for i in range(1, 6)]    # ['3.1', '3.14', '3.142', '3.1416', '3.14159']
# 嵌套列表解析
matrix = [
    [1, 2, 3, 4],
    [5, 6, 7, 8],
    [9, 10, 11, 12]
]
# 将其转换成4X3矩阵列表
# 方法一(直接用列表解析做)
[[row[i] for row in matrix] for i in range(4)]    # [[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
# 方法二(对内层列表用列表解析然后添加至外层列表)
transposed = []
for i in range(4): 
    transposed.append([row[i] for row in matrix])
print(transposed)    # [[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
# 方法三(两层循环,先生成内层列表,没生成一个添加至外层列表)
transposed = []
for i in range(4):
    transposed_row = []
    for row in matrix:
        transposed_row.append(row[i])
    transposed.append(transposed_row)
print(transposed)    # [[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
# del 语句
# 使用 del 语句可以从一个列表中依索引而不是值来删除一个元素。这与使用 pop() 返回一个值不同。可以用 del 语句从列表中删除一个切割,或清空整个列表
a = [-1, 1, 66.25, 333, 333, 1234.5]
del a[0]
pritn(a)    # [1, 66.25, 333, 333, 1234.5]
del a[2:4]
print(a)    # [1, 66.25, 1234.5]
del a[:]
print(a)    # []
# 也可以用 del 删除实体变量:
del a

2.5  Dictionary

键必须是唯一的,但值不必

值可以取任何数据类型,但键必须是不可变的,如字符串、数字或元组

· clear()
删除字典内所有元素
· copy()
返回一个字典的浅复制
· fromkeys()

创建一个新字典,以序列seq中元素做字典的键,val为字典所有键对应的初始值

{}.fromkeys([1, 2, 3], 'she')
# {1: 'she', 2: 'she', 3: 'she'}
· get(key, default=None)
返回指定键的值,如果值不在字典中返回default值
· key in dict
如果键在字典dict里返回true,否则返回false
· items()
以列表返回可遍历的(键, 值) 元组数组
· keys()
以列表返回一个字典所有的键
· setdefault(key, default=None)
和get()类似, 但如果键不存在于字典中,将会添加键并将值设为default
· update(dict2)
把字典dict2的键/值对更新到dict里
· values()
以列表返回字典中的所有值
· pop(key[,default])
删除字典给定键 key 所对应的值,返回值为被删除的值。key值必须给出。 否则,返回default值。
· popitem()

随机返回并删除字典中的一对键和值(一般删除末尾对)。

# 序列的遍历技巧
# 在字典中遍历时,关键字和对应的值可以使用 items() 方法同时解读出来
knights = {'gallahad': 'the pure', 'robin': 'the brave'}
for k, v in knights.items():
    print(k, v)
# gallahad the pure
# robin the brave
# 在序列中遍历时,索引位置和对应值可以使用 enumerate() 函数同时得到:
for i, v in enumerate(['tic', 'tac', 'toe']):
    print(i, v)
# 0 tic
# 1 tac
# 2 toe
# 同时遍历两个或更多的序列,可以使用 zip() 组合:
questions = ['name', 'quest', 'favorite color']
answers = ['lancelot', 'the holy grail', 'blue']
for q, a in zip(questions, answers):
    print('What is your {0}?  It is {1}.'.format(q, a))
# What is your name?  It is lancelot.
# What is your quest?  It is the holy grail.
# What is your favorite color?  It is blue.
# 要反向遍历一个序列,首先指定这个序列,然后调用 reversed() 函数:
for i in reversed(range(1, 10, 2)):
    print(i, end=' ')    # 9 7 5 3 1
# 要按顺序遍历一个序列,使用 sorted() 函数返回一个已排序的序列,并不修改原值:
basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
for f in sorted(set(basket)):
    print(f, end=' ')    # apple banana orange pear

2.6  迭代器与生成器

2.6.1  迭代器

· 迭代是访问集合元素的一种方式
· 迭代器是一个可以记住遍历的位置对象
· 迭代器对象从集合的第一个元素开始访问,直到所有的元素都被访问完结束。迭代器只能往前不会后退
· 迭代器有两个基本的方法:iter()和next()
· 字符串、列表或元组对象都可以用于创建迭代器
· 字典创建迭代器时迭代的是字典的键(key)

lst = [1, 2, 3]
it = iter(lst)
print(next(it))
# 1
print(next(it))
# 2
print(next(it))
# 3
print(next(it))
# StopIteration

迭代器对象可以用常规的for...in语句进行遍历

lst = [1, 2, 3]
it = iter(lst)
for x in it:
    print(x, end=' ')
# 1 2 3

使用next()函数和while循环

import sys
lst = [1, 2, 3]
it = iter(lst)
while True:
    try:
        print(next(it), end=' ')
    except StopIteration:
        sys.exit()
# 1 2 3
2.6.2  生成器

· 使用yield的函数被称为生成器(generator)
· 生成器是一个返回迭代器的函数,只能用于迭代操作
· 在调用生成器运行的过程中,每次遇到yield时函数会暂停并保存当前所有的运行信息,返回yield的值,并在下一次执行next方法时从当前位置继续运行

一个带有 yield 的函数就是一个 generator,它和普通函数不同,生成一个 generator 看起来像函数调用,但不会执行任何函数代码,直到对其调用 next()(在 for 循环中会自动调用 next())才开始执行。虽然执行流程仍按函数的流程执行,但每执行到一个 yield 语句就会中断,并返回一个迭代值,下次执行时从 yield 的下一个语句继续执行。看起来就好像一个函数在正常执行的过程中被 yield 中断了数次,每次中断都会通过 yield 返回当前的迭代值。

def fab(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b
        a, b = b, a + b
        n += 1
for n in fab(5):
    print(n, end=' ')
# 1, 1, 2, 3, 5

如何判断一个函数是否是一个特殊的generator函数?可以利用isgeneratorfunction判断:

from inspect import isgeneratorfunction
isgeneratorfunction(fab)
# True

要注意区分 fab 和 fab(5),fab 是一个 generator function,而 fab(5) 是调用 fab 返回的一个 generator,好比类的定义和类的实例的区别:

import types
isinstance(fab, types.GeneratorType)
# False
isinstance(fab(5), types.GeneratorType)
# True

fab 是无法迭代的,而 fab(5) 是可迭代的:

from collections import Iterable
isinstance(fab, Iterable)
# False
isinstance(fab(5), Iterable)
# True

2.7  函数

2.7.1  变量类型

在 python 中,strings, tuples, 和 numbers 是不可更改的对象,而 list,dict 等则是可以修改的对象。


不可变类型:变量赋值 a=5 后再赋值 a=10,这里实际是新生成一个 int 值对象 10,再让 a 指向它,而 5 被丢弃,不是改变a的值,相当于新生成了a。
可变类型:变量赋值 la=[1,2,3,4] 后再赋值 la[2]=5 则是将 list la 的第三个元素值更改,本身la没有动,只是其内部的一部分值被修改了。

python 函数的参数传递:

不可变类型:类似 c++ 的值传递,如 整数、字符串、元组。如fun(a),传递的只是a的值,没有影响a对象本身。比如在 fun(a)内部修改 a 的值,只是修改另一个复制的对象,不会影响 a 本身。
可变类型:类似 c++ 的引用传递,如 列表,字典。如 fun(la),则是将 la 真正的传过去,修改后fun外部的la也会受影响

python 中一切都是对象,严格意义我们不能说值传递还是引用传递,我们应该说传不可变对象和传可变对象。

2.7.2  匿名函数:

python使用lambda来创建匿名函数
所谓匿名,意即不再使用 def 语句这样标准的形式定义一个函数。
· lambda 只是一个表达式,函数体比 def 简单很多。
· lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。
· lambda 函数拥有自己的命名空间,且不能访问自己参数列表之外或全局命名空间里的参数。
lambda函数的语法:

lambda [arg1[, arg2,...,argn]]: expression

sum = lambda x, y: x + y
sum(37, 73)    # 110
2.7.3  变量作用域

L(Local):局部作用域

E(Enclosing):闭包函数外的函数中
G(Global):全局作用域
B(Built-in):内建作用域
以 L –> E –> G –>B 的规则查找,即:在局部找不到,便会去局部外的局部找(例如闭包),再找不到就会去全局找,再者去内建中找。

x = int(2.9)  # 内建作用域
 
g_count = 0  # 全局作用域
def outer():
    o_count = 1  # 闭包函数外的函数中
    def inner():
        i_count = 2  # 局部作用域

Python 中只有模块(module),类(class)以及函数(def、lambda)才会引入新的作用域,其它的代码块(如 if/elif/else/、try/except、for/while等)是不会引入新的作用域的,也就是说这些语句内定义的变量,外部也可以访问,如下代码:

if True:
    msg = 'she loves cat'
print(msg)    # she loves cat
2.7.4  全局变量和局部变量

定义在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全局作用域。局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内访问。调用函数时,所有在函数内声明的变量名称都将被加入到局部作用域中。如下实例:

total = 0; # 这是一个全局变量
# 可写函数说明
def sum( arg1, arg2 ):
    #返回2个参数的和."
    total = arg1 + arg2; # total在这里是局部变量.
    print ("函数内是局部变量 : ", total)
    return total;

#调用sum函数
sum( 10, 20 );
print ("函数外是全局变量 : ", total)

global和nonlocal关键字:
当内部作用域向修改外部作用域的变量时,就要用到global和nonlocal关键字了。

修改全局变量num:

num = 1
def change():
    global num
    print(num)    # 1
    num = 73
    print(num)    # 73
print(num)    # 73

修改嵌套作用域变量num:

def outer():
    num = 1
    def inner():
        nonlocal num
        num = 73
        print(num)
    inner()
    print(num)
outer()    # 73 73

另外有一种特殊情况,假设下面这段代码被运行

a = 10
def test():
    a = a + 1
    print(a)
test()
# Traceback (most recent call last): 
#   File "test.py", line 7, in <module>
#     test()
#   File "test.py", line 5, in test
#     a = a + 1 
# UnboundLocalError: local variable 'a' referenced before assignment

第 3 章  模块、输入和输出、File、OS、错误和异常

3.1  模块

3.1.1  import语句

· 一个模块只会被导入一次,不管你执行了多少次import。这样可以防止导入模块被一遍又一遍执行。
· 模块的搜索顺序:
  1) 搜索当前目录指定的模块文件名,如果有就直接导入
  2) 否则搜索系统目录
· 给文件起名时,不要和系统的模块文件重名
· python中每一个模块都有一个内置属性__file__可以查看模块的完整路径
· 在导入文件时,文件中所有没有任何缩进的代码都会被执行一遍

· 模块向外界提供的工具应该有:全局变量、函数、类,而能够直接执行的代码并不是向外界提供的工具(例如每个模块中含有的测试代码,被导入到其他文件中,这些测试代码不需要执行)

· 模块除了方法定义,还可以包括可执行的代码。这些代码一般用来初始化这个模块。这些代码只有在第一次被导入时才会被执行

import amodule as module_alias(建议使用大驼峰命名法)

若两个模块存在同名函数,那么后导入模块的函数会覆盖先导入的函数。一旦发现冲突可使用as关键字给其中一个起别名。

3.1.2  dir函数

内置的函数 dir() 可以找到模块内定义的所有名称。以一个字符串列表的形式返回

应该注意到这有一个特别的模块 sys ,它内置在每一个 Python 解析器中。变量 sys.ps1 和 sys.ps2 定义了主提示符和副提示符所对应的字符串:

>>> import sys
>>> sys.ps1    # '>>>'
>>> sys.ps2    # '...'
>>> sys.ps1 = 'G>>'
G>> print('python')    # python
G>> 
3.1.3  包

· 包是一种管理python模块命名空间的形式,采用“点模块名”
· 在导入一个包时,python会根据sys.path中的目录来寻找这个包中包含的子目录
· 目录只有包含一个叫做__init__.py的文件才会被认作是一个包
· 如果使用形如import item.subitem.subsubitem这种导入形式,除了最后一项,都必须是包,而最后一项则可以是模块或者是包,但是不可以是类,函数或者变量的名字。

· 当使用from package import item这种形式的时候,对应的item既可以是包里面的子模块(子包),或者包里面定义的其他名称,比如函数,类或者变量。 import语法会首先把item当作一个包定义的名称,如果没找到,再试图按照一个模块去导入。如果还没找到,恭喜,一个:exc:ImportError 异常被抛出了。

eg:

sound/                          顶层包
      __init__.py               初始化 sound 包
      formats/                  文件格式转换子包
              __init__.py
              wavread.py
              wavwrite.py
              aiffread.py
              aiffwrite.py
              auread.py
              auwrite.py
              ...
      effects/                  声音效果子包
              __init__.py
              echo.py
              surround.py
              reverse.py
              ...
      filters/                  filters 子包
              __init__.py
              equalizer.py
              vocoder.py
              karaoke.py

从一个包中导入*:

· 如果包定义文件 __init__.py 存在一个叫做 __all__ 的列表变量,那么在使用 from package import * 的时候就把这个列表中的所有名字作为包内容导入。 作为包的作者,可别忘了在更新包之后保证 __all__ 也更新了啊。

例子,file:sounds/effects/__init__.py中包含如下代码: __all__ = ["echo", "surround", "reverse"]

这表示当你使用from sound.effects import *这种用法时,你只会导入包里面这三个子模块。 如果 __all__ 真的没有定义,那么使用from sound.effects import *这种语法的时候,就不会导入包 sound.effects 里的任何子模块。他只是把包sound.effects和它里面定义的所有内容导入进来(可能运行__init__.py里定义的初始化代码)。 这会把 __init__.py 里面定义的所有名字导入进来。并且他不会破坏掉我们在这句话之前导入的所有明确指定的模块。

如果在结构中包是一个子包(比如这个例子中对于包sound来说),而你又想导入兄弟包(同级别的包)你就得使用导入绝对的路径来导入。比如,如果模块sound.filters.vocoder 要使用包sound.effects中的模块echo,你就要写成 from sound.effects import echo。 

from . import echo
from .. import formats
from ..filters import equalizer

3.2  输入和输出

python两种输出值的格式:表达式和print()函数
第三种方式是使用文件对象的write()方法,标准输出文件可以用sys.stdout引用
如果希望输出的形式更加多样,可以使用str.format()函数来格式化输出值
如果希望将输出的值转成字符串,可以使用repr()或str()函数来实现

str():返回一个用户易读的表达式    repr():产生一个解释器易读的表达式

1.  repr()函数可以转义字符串中的特殊字符:

hello = 'hello, sunyu\n'
print(hello)
# hello sunyu

print(repr(hello))
# hello sunyu\n

2.  str.format()基本使用:

print('{}\'s link: "{}"'.format('baidu', 'www.baidu.com'))    # baidu's link: "www.baidu.com"
# 括号及其里面对字符(称作格式化字段)将会被format中的参数替换
# 在括号中的数字用于指向传入对象在format()中的位置
print('{1} and {0}'.format('Rose', 'Jack'))    # Jack and Rose
# 如果在format()中使用了关键字参数,那么它们的值会指向使用该名字的参数
print('{name} is a {job}'.format(name='yh', job='student'))    # yh is a student
# 位置和关键字参数可以任意的结合
print('站点列表 {0}, {1}, 和 {other}。'.format('Google', 'Runoob', other='Taobao'))
# 站点列表 Google, Runoob, 和 Taobao。
# !a(使用ascii()), !s(使用str()),!r(使用repr())可以用于在格式化某个值之前对其进行转化
import math
print('pi\'s similar value is: {}'.format(math.pi))    # pi's similar value is: 3.141592653589793
print('pi\'s similar value is: {!s}'.format(math.pi))    # pi's similar value is: 3.141592653589793
# 可选项:和格式符可以跟着字段名。这就允许对值进行更好的格式化
print('pi\'s similar value is: {0:.3f}'.format(math.pi))    # pi's similar value is: 3.142
# 在:后传入一个整数,可以保证该域至少有这么多的宽度
for name, number in site_dict.items():
    print('{0:10} ==> {1:10d}'.format(name, number))
# Google     ==>          1
# Runoob     ==>          2
# TaoBao     ==>          3
# 传入一个字典,然后使用方括号来访问值
print('Google:{0[Google]:3d}; Runoob:{0[Runoob]:3d}; TaoBao:{0[TaoBao]:3d}'.format(site_dict))    # Google:  1;  Ruoob:  2; TaoBao:  3
# 通过在table变量前使用'**'来实现相同的功能
print('Google:{Google:3d}; Runoob:{Runoob:3d}; TaoBao:{TaoBao:3d}'.format(**site_dict))    # Google:  1;  Ruoob:  2; TaoBao:  3

3.  读和写文件:

open()将会返回一个file对象,基本语法格式如下:

open(filename, mode):filename —> 包含了你要访问的文件名称的字符串值    mode:决定了打开文件的模式,默认只读

mode描述
r 以只读方式打开文件,文件的指针将会放在文件的开头
rb以二进制格式打开一个文件用于只读,文件的指针将会放在文件的开头
r+打开一个文件用于读写,文件的指针将会放在文件的开头
rb+以二进制格式打开一个文件用于读写,文件的指针将会放在文件的开头
w打开一个文件只用于写入,如果该文件已存在则将其覆盖;如果文件不存在则创建新文件
wb以二进制格式打开一个文件只用于写入,如果文件已存在则将其覆盖;如果文件不存在则创建新文件
w+打开一个文件用于读写,如果该文件已存在则将其覆盖;如果文件不存在则创建新文件
wb+以二进制格式打开一个文件用于读写,如果该文件已存在则将其覆盖;如果文件不存在则创建新文件
a打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的末尾;如果文件不存在则创建新文件进行写入
ab以二进制格式打开一个文件用于追加。
a+打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的末尾,文件打开时是追加模式;如果文件不存在则创建新文件
ab+y以二进制格式打开一个文件用于追加。

4.  文件对象的方

· f.read():为了读取一个文件的内容,调用f.read(size),这将读取一定数目的数据,然后作为字符串或字节对象返回。size是一个可选的数字类型的参数,当size被忽略了或者为负,那么该文件所有的内容都将被读取并且返回

· f.readline():从文件中读取单独的一行。换行符为'\n',f.readline()如果返回一个空字符串,说明已经读到最后一行
· f.readlines():返回文件中包含的所有行。如果设置可选参数sizeint,则读取指定长度的字节,并且将这些字节按行分割
· f.write(string):将string写入到文件中,然后返回写入的字符数
· f.tell():返回文件对象当前所处的位置,它是从文件开头开始算起的字节数
· f.seek(offset, from_what):from_what的值:0表示开头,1表示当前位置,2表示文件的末尾。默认值为0
    seek(x, 0):从起始位置即文件首行首字符开始移动x个字符
    seek(x, 1):表示从当前位置往后移动x个字符
    seek(-x, 2):表示从文件结尾往前移动x个字符

· f.close():在文本文件中(那些打开文件模式没有b的),只会相对于文件起始位置进行定位。当你处理完一个文件后,调用f.close()来关闭文件并释放系统资源,如果尝试再调用该文件,则会抛出异常

当处理一个文件对象时,使用with关键字是非常好的方式,在结束后他会帮你正确关闭文件:

with open('input_ouput.txt') as f:
    f.seek(16)
    read_data = f.read(12)
    print(read_data)
# he loves cat

迭代一个文件对象然后读取每行:

f =  open('input_ouput.txt')
for line in f:
    print(line, end='')
# she loves cat.
# he loves cat, too.
# she also loves dog.
# he love her.
# he says he loves her whatever happens.

5.  pickle模块

实现了基本的数据序列和反序列化。

通过pickle模块的序列化操作我们能够将程序中运行的对象信息保存到文件中去,永久存储

通过pickle模块的反序列化操作我们能够从文件中创建上一次程序保存的对象

基本接口:pickle.dump(obj, file[, protocol])

pickle.load(file)

eg:

import pickle, pprint
data1 = {'a': [1, 2.0, 7 + 3j],
         'b': 'she loves cat',
         'c': None}
boring_list = ['sun', 'yu']
boring_list.add(boring_list)
output = open('data.pkl', 'wb')
pickle.dump(data1, output)    # 使用协议0存储
pickle.dump(boring_list, ouput, -1)    # 使用最高可用协议来存储
output.close()
pkl_file = open('data.pkl', 'rb')    # 使用pickle模块从文件中重构python对象
data1 = pickle.load(pkl_file)
pprint.pprint(data1)    # pprint是标准化输出,可测试一下与print的区别
# {'a': [1, 2.0, (7 + 3j)], 'b': 'she loves cat', 'c': None}
data2 = pickle.load(pkl_file)
pprint.pprint(data2)
# ['sun', 'yu', <Recursion on list with id=2353306677640>]
pkl_file.close()

3.3  File

file对象使用open函数来创建,file对象常用函数:

· file.close():关闭文件,关闭后文件不能再进行读写操作
· file.flush():刷新文件内部缓冲区
· file.fileon():返回一个整型文件描述符(file descriptor)
· file.atty():如果文件连接到一个终端设备返回True,否则返回False

· file.next():返回文件下一行。Python 3 中的 File 对象不支持 next() 方法。 Python 3 的内置函数 next() 通过迭代器调用 __next__() 方法返回下一项。 在循环中,next()方法会在每次循环中调用,该方法返回文件的下一行,如果到达结尾(EOF),则触发 StopIteration

with open('input_ouput.txt') as f:
    for index in range(5):
        read_data = next(f)
        print('The {} row - {}'.format(index+1, read_data))
# The 1 row - she loves cat.

The 2 row - he loves cat, too.

The 3 row - she also loves dog.

The 4 row - he loves her.

The 5 row - he says he loves her whatever happens.
· filefile.read([size]):从文件读取指定字节数,如果未给定或为负则读取所有
· file.readline([size]):读取整行,包括'\n'

· file.readlines([sizeint]):读取所有行并返回列表(可以测试一下不同sizeint的值,'\n'不计入sizeint)

with open('input_ouput.txt') as f:
    f.readlines(1)
# ['she loves cat.\n']
with open('input_ouput.txt') as f:
    f.readlines(15)
# ['she loves cat.\n', 'he loves cat, too.\n']
with open('input_ouput.txt') as f:
    f.readlines(14)
# ['she loves cat.\n']
· file.seek(offset[, whence]):设置文件当前位置
· file.tell():返回文件当前位置

· file.truncate([size]):从文件的首行首字符开始截断,截断文件为size个字符,无size表示从当前位置截断。截断之后V后面的所有字符被删除,其中Windows系统下的换行代表2个字符大小
· file.write(str):将字符串写入文件,没有返回值
· file.writelines(sequence):向文件写入一个序列字符串,如果需要换行则要自己加入每行的换行符

3.4  OS

(Temporarily omitted)

3.5  错误和异常

try:

  pass
except:

  pass

try:
  pass
except Error1:
  pass
except (Error2, Error3):
  pass
except:    —> 被当做通配符使用

  pass

try:
  pass
except:
  pass
else:
  pass    # 只有在没有异常时才会执行的代码
finally:

  pass

主动抛出异常:
  python中提供了Exception异常类
  为满足特定业务需求,希望抛出异常:首先创建一个Exception对象;其次使用raise关键字抛出异常

第 四 章  面向对象

1. 类的专有方法:

· __init__:构造函数,在生成对象时调用
· __del__:析构函数,释放对象时调用
· __repr__:打印,转换
· __setitem__:按照索引赋值
· __getitem__:按照索引取值
· __len__:获得长度
· __cmp__:比较运算
· __call__:函数调用
· __add__:加运算
· __sub__:减运算
· __mul__:乘运算
· __div__:除运算
· __mod__:求余运算

· __pow__:乘方

2. 运算符重载:

第 五 章  正则表达式

正则表达式是一个特殊的字符序列,能够方便的检查一个字符串是否与某种模式匹配。

5.1  re.match

re.match函数:尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回None

re.match(pattern, string, flags=0)

参数m描述
pattern匹配的正则表达式
string要匹配的字符串
flagsb标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等

匹配成功re.match方法返回一个匹配的对象,否则返回None

可以使用group(num)或groups()匹配对象函数来获取匹配表达式

匹配对象方法m描述
group(num=0)匹配整个表达式的字符串,group()可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组
groups()返回一个包含所有小组字符串的元组,从1到所含的小组号

eg

print(re.match('she loves cat', 'she loves cat www.baidu.com').span())    # (0, 13) ——> 返回一个匹配串在字符串中的跨度的元组
print(re.match('she loves cat', 'he loves her, she loves cat www.baidu.com').span())
# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
# AttributeError: 'NoneType' object has no attribute 'span'
print(re.match('she loves cat', 'he loves her, she loves cat www.baidu.com'))    # None
import re
line = "Cats are smarter than dogs"
matchObj = re.match( r'(.*) are (.*?) .*', line, re.M|re.I)
if matchObj:
    print ("matchObj.group() : ", matchObj.group())
    print ("matchObj.group(1) : ", matchObj.group(1))
    print ("matchObj.group(2) : ", matchObj.group(2))
    print('matchObj.groups(): ', matchObj.groups())
else: 
    print ("No match!!")
# matchObj.group() :  Cats are smarter than dogs
# matchObj.group(1) :  Cats
# matchObj.group(2) :  smarter
# matchObj.groups():  ('Cats', 'smarter')

5.2  re.search

re.search扫描整个字符串并返回第一个成功的匹配

re.search(pattern, string, flags=0)

eg:

print(re.search('she loves cat', 'he loves her, she loves cat www.baidu.com').span())    # (14, 27)

与re.match区别:re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,直到找到一个匹配。

5.3  re.sub

re.sub()用于替换字符串中的匹配项

re.sub(pattern, repl, string, count=0)

参数描述
pattern正则中的模式字符串
repl替换的字符串,也可为一个函数
string要被查找替换的原始字符串
count模式匹配后替换的最大次数,默认0表示替换所有的匹配

eg

import re
phone = '186-2904-1907 # This is a phone number.'
# delete comments
phone_num = re.sub(r'#.$', '', phone)    # phone number:  186-2904-1907
# remove the content not a digital
phone_num = re.sub(r'\D', '', phone)    #  phone number:  18629041907

repl参数是一个函数的例子:

import re
def double(matched):
    value = int(matched.group('value'))
    return str(value * 2)
s = 'she23loves7cat520'
print(re.sub('(?P<value>\d+)', double, s))    # she46loves14cat1040

5.3  re.compile

compile函数用于编译正则表达式,生成一个正则表达式(Pattern)对象,供match()和search()这两个函数使用

re.compile(pattern[, flags])
· pattern:一个字符串的形式的正则表达式
· flags:表示匹配模式,比如忽略大小写,多行模式等
    · re.l  忽略大小写
    · re.L  表示特殊字符集\w, \W, \b, \B, \s, \S依赖于当前环境
    · re.M  多行模式

    · re.S  即为'.'并且包括换行符在内的任意字符('.'不包括换行符)
    · re.U  表示特殊字符集 \w, \W, \b, \B, \d, \D, \s, \S 依赖于 Unicode 字符属性数据库

    · re.X  为了增加可读性,忽略空格和‘#’后面的注释

import re
pattern = re.compile(r'\d+')
m = pattern.match('one12twothree34four')
print(m)    # None
m = pattern.match('one12twothree34four', 3, 7)
print(m)    # <_sre.SRE_Match object; span=(3, 5), match='12'>
m.group()    # '12'
m.start()    # 3
m.end()    # 5
m.span()    # (3, 5)
import re
pattern = re.compile(r'([a-z]+) ([a-z]+)', re.I)
m = pattern.match('Hello SunYu I want to approach to you')
print(m)    # <_sre.SRE_Match object; span=(0, 11), match='Hello SunYu'>
m.group()    # 'Hello SunYu'
m.span()    # (0, 11)
m.group(1)    # 'Hello'
m.span(1)    # (0, 5)
m.group(2)    # 'SunYu'
m.span(2)    # (6, 11)
m.groups()    # ('Hello', 'SunYu')

5.4  findall

在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表。 
注意: match 和 search 是匹配一次 findall 匹配所有。
findall(string[, pos[, endpos]])
· string 待匹配的字符串。
· pos 可选参数,指定字符串的起始位置,默认为 0。

· endpos 可选参数,指定字符串的结束位置,默认为字符串的长度。

import re
pattern = re.compile(r'\d+')   # 查找数字
result1 = pattern.findall('runoob 123 google 456')
result2 = pattern.findall('run88oob123google456', 0, 10)
print(result1)    # ['123', '456']
print(result2)    # ['88', '12']

5.5  re.finditer

和 findall 类似,在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个迭代器返回。
finditer(pattern ,string, flags=0)

import re
it = re.finditer(r"\d+","12a32bc43jf3") 
for match in it: 
    print (match.group() )
# 12    (str)
# 32
# 43
# 3

5.6  re.split

split 方法按照能够匹配的子串将字符串分割后返回列表,它的使用形式如下:
re.split(pattern, string[, maxsplit=0, flgas=0])
· pattern  匹配的正则表达式
· string  要匹配的字符串。
· maxsplit  分隔次数,maxsplit=1 分隔一次,默认为 0,不限制次数。

>>>import re
>>> re.split('\W+', 'runoob, runoob, runoob.')
['runoob', 'runoob', 'runoob', '']
>>> re.split('(\W+)', ' runoob, runoob, runoob.') 
['', ' ', 'runoob', ', ', 'runoob', ', ', 'runoob', '.', '']
>>> re.split('\W+', ' runoob, runoob, runoob.', 1) 
['', 'runoob, runoob, runoob.'] 
>>> re.split('a*', 'hello world')   # 对于一个找不到匹配的字符串而言,split 不会对其作出分割
['hello world']

5.7  正则表达式对象

re.RegexObject:re.compile返回RegexObject对象
re.MatchObject:re.match返回MatchObject对象

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

5.8  正则表达式修饰符 - 可选标志

正则表达式可以包含一些可选标志修饰符来控制匹配的模式。修饰符被指定为一个可选的标志,多个标志可以通过按位OR(|)来指定,例如:re.l | re.M被设置成l和M的标志:

修饰符描述
re.l使匹配对大小写不敏感
re.L(省略)
re.M多行匹配,影响^和$
re.S使 '.' 匹配包括行在内的所有字符
re.U(省略)
re.X该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。

5.9  正则表达式模式

模式字符串使用特殊的语法来表示一个正则表达式:

· 字母和数字表示他们自身,一个正则表达式模式中的字母和数字匹配同样的字符串
· 多数字母和数字前加一个反斜杠时会拥有不同的含义
· 标点符号只有被转义时才匹配自身,否则它们表示特殊的含义

· 反斜杠本身需要使用反斜杠转义

· 由于正则表达式通常都包含反斜杠,所以最好使用原始字符串来表示它们。

模式描述
^匹配字符串的开头
$匹配字符串的末尾
.匹配任意字符,除了换行符
[...]用来表示一组字符,eg:[abc]匹配'a'、'b'或'c'
[^...]不在[]中的字符,eg:[^abc]匹配除了a、b、c之外的字符
re*匹配0个或多个的表达式
re+匹配1个或多个的表达式
re?匹配0个或1个由前面的正则表达式定义的片段
re{n}匹配n个前面的表达式。例如,'o{2}'不能匹配'Pop'中的'o',但是能匹配'root'中的两个o
re{n,}精确匹配n个前面表达式。例如,'o{2,}'不能匹配'Pop'中的'o',但是能匹配'rooooooot'中的所有o。'o{1,}'等价于'o+','o{0,}'等价于'o*'
re{n, m}匹配n到m次由前面的正则表达式定义的片段
a | b匹配a或b
(re)匹配括号内的表达式
(?imx)正则表达式包括三种可选标志:i, m, x,只影响括号中的区域
(?-imx)正则表达式关闭i, m, x可选标志。只影响括号中的区域
(?: re)类似 (...), 但是不表示一个组
(?imx: re)在括号中使用i, m, 或 x 可选标志
(?-imx: re)在括号中不使用i, m, 或 x 可选标志
(?#...)注释.
(?= re)前向肯定界定符。如果所含正则表达式,以 ... 表示,在当前位置成功匹配时成功,否则失败。但一旦所含表达式已经尝试,匹配引擎根本没有提高;模式的剩余部分还要尝试界定符的右边。
(?! re)前向否定界定符。与肯定界定符相反;当所含表达式不能在字符串当前位置匹配时成功。
(?> re)匹配的独立模式,省去回溯。
\w匹配数字字母下划线
\W匹配非数字字母下划线
\s匹配任意空白字符,相当于[\t\n\r\f]
\S匹配任意非空字符
\d匹配任意数字,等价于[0-9]
\D匹配任意非数字
\A匹配字符串开始
\Z匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符
\z匹配字符串结束
\G匹配最后匹配完成的位置
\b匹配一个单词边界,也就是指单词和空格间的位置,例如,'er\b'可以匹配'never'中的'er',但不能匹配'verb'中的er
\B匹配非单词边界,例如,'er\B'不能匹配'never'中的'er',但能匹配'verb'中的er
\n,\t匹配一个换行符,匹配一个制表符
\1...\9匹配第n个分组的内容
\10匹配第n个分组的内容,如果它经匹配。否则指的是八进制字符码的表达式。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值