C函数定义 的语法是递归定义的,正则表达式 的一大缺陷就是无法匹配递归定义的规则
从策划到设计制作,每一步都追求做到细腻,制作可持续发展的企业网站。为客户提供网站设计、网站制作、网站策划、网页设计、主机域名、虚拟主机、网络营销、VI设计、 网站改版、漏洞修补等服务。为客户提供更好的一站式互联网解决方案,以客户的口碑塑造优易品牌,携手广大客户,共同发展进步。
你写的正则表达式没有错,只是你用的Python函数re.search()只能匹配一次,如果要匹配多次需要用re.findall()函数,它返回一个list.改正后完整的Python程序如下
import re
fw = 'span class="price"16000span class="danwei"span class="price"待定span class="danwei"'
pattern = re.compile(r'span class="price"(.*?)span class=\"danwei"')
result = re.findall(pattern,fw)
print(result)
match()函数只检测RE是不是在string的开始位置匹配,
search()会扫描整个string查找匹配;
也就是说match()只有在0位置匹配成功的话才有返回,
如果不是开始位置匹配成功的话,match()就返回none。
例如:
print(re.match('super', 'superstition').span()) 会返回(0, 5)
而print(re.match('super', 'insuperable')) 则返回None
search()会扫描整个字符串并返回第一个成功的匹配
例如:print(re.search('super', 'superstition').span())返回(0, 5)
print(re.search('super', 'insuperable').span())返回(2, 7)
其中span函数定义如下,返回位置信息。
span([group]):
返回(start(group), end(group))。
效果如下图:
一、前言
在python中,函数参数的定义和传递有以下几种方式:
语法
意义
def func(name)
普通参数,可以根据位置匹配,也可以根据key来匹配
def func(name=value)
默认参数,当参数没有传递时,使用默认值
def func(*iteratable)
将所有剩下的未匹配的参数收集至一个tuple中
def func(**dictionary)
将剩下未匹配的参数收集值一个dict中
def func(*, name)
必须使用key来匹配参数
def func(*other, name)
必须使用key来匹配参数
func(value)
函数调用,参数值按传递的参数顺序匹配
func(name=value)
函数调用,参数值根据key来匹配
func(*iteratable)
函数调用,将iteratable容器中的参数展开,按位置匹配对应的函数参数
func(**dictionary)
函数调用,将dict中的参数展开,按key值来匹配对应的函数参数
在python中,参数可以按照顺序传递,在调用函数时,参数的值按照传递的顺序,从左到右依次匹配。并且还可以给参数传递默认值,这都很好理解,因为在C、C++、Java等许多语言中,函数的参数传递都是按照这种方法来传递的。
但python的参数定义和传递除了按照顺序传递以及可以给默认值外,它还有其它的一些特点,在进一步讲解之前,首先说明python中函数调用中参数匹配的顺序:
按照顺序,给没有key的参数赋值,意味着传递参数时,需按顺序匹配的参数必须出现在按key匹配的参数之前;
给按照key匹配的参数赋值;
将多余的按照顺序匹配但未匹配的参数值归入*name的tuple中;
将多余未匹配上的按照key进行匹配的参数值归入**name的dict对象中;
将为匹配上的且具有默认值的参数赋默认值
二、按key匹配参数
对于C、C++这种语言,在调用函数时,系统会首先将函数地址压入堆栈,其次按参数的从右往左的顺序,一次压入堆栈。因此,C、C++这种语言它们只支持按顺序匹配形参。而python的做法不同,参数除了可以按顺序匹配,还可以按照参数名称来匹配。如:
def func(name, age):
print(name, age)
对于这个函数,以下的调用时等价的:
func('rechar', 27) #按顺序匹配
func(name = 'rechar', age = 27) #按参数名称匹配,在运行时告诉系统参数name的值为‘rechar’,age的值为27
func(age = 27, name = 'rechar') #按参数名称匹配
func('rechar', age = 27) #name是按顺序匹配,age按名称匹配
在python中,当按照参数名称进行匹配参数是,参数传递的顺序是可以任意的,不要求按照函数定义中参数的顺序进行传递。在使用名称匹配时,如果需要混合使用按顺序匹配规则,则按顺序匹配的参数必须出现在按key匹配的参数前,否则会报错:
func(name = 'rechar', 27)
以上调用会报如下错误:
三、函数定义中的”*name“
python在给按顺序匹配和按key匹配的参数赋完值后,如果发现调用者传入的参数仍有未匹配上的会发生什么情况呢?看一下下面的例子:
func('rechar', 27, 32)
运行时我们看到如下错误:
Traceback (most recent call last):
File "E:\tmp\tt.py", line 5, in module
func('rechar', 27, 32)
TypeError: func() takes 2 positional arguments but 3 were given
哦,python会抱怨我们传递的参数太多了。那如果确实在一些情况下,我们无法保证传递的参数数量一定和函数需要的参数数相等怎么办呢?这是就是*iterable这种参数该登场的时候了,假如在定义函数定义是,我们增加了一个参数,这个参数以一个”*“开始,那么这个参数实际上是一个tuple类型。假如传递的参数比需要的多,那那些多余的参数会被放入这个tuple中。例如,
def func(name, age, *other):
print(name, age, other)
那么,
func('rechar', 27, 32)
这个调用的输出如下:
rechar 27 (32,)
四、函数定义中的”**name“
python在将所有未匹配上的非按名称匹配的参数装入参数中的tuple之后,假如还有未匹配上的按名称匹配的参数那情况会怎样呢?首先来看一下下面的示例:
def func(name, age):
print(name, age)
func(name = 'rechar', age = 27, pay='1800')
执行时,python又抱怨了:
Traceback (most recent call last):
File "E:\tmp\tt.py", line 5, in module
func(name = 'rechar', age = 27, pay='1800')
TypeError: func() got an unexpected keyword argument 'pay'
它说func这个函数没有名称为”pay“的参数,这种情况或许出现在我们函数重构之后,原来函数时有这个参数的。而这个函数调用可能在别处没有被修改。假设即使给了”pay“这个参数,程序的正确性不受影响,没错,这就是”**name“参数的用武之地了。
假如在函数定义中,给函数增加一个以”**“开头的参数,那么这个参数实际上是一个dict对象,它会将参数调用中所有没有被匹配的按名称传递的参数都放入这个dict中。例如,
def func(name, age,**other):
print(name, age, other)
func(name = 'rechar', age = 27, pay='1800')
那么运行结果输出,
rechar 27 {'pay': '1800'}
看到了吧,这里的other就将没有匹配的”pay=‘1800’“收入囊中了。
五、规定调用必须按名称匹配
当我们在定义函数时,如果第一个参数就是”*name“参数,那么可想而知,我们无法使用按顺序匹配的方式传递,因为所有的按顺序传递的参数值最终的归宿都会是这里的tuple当中。而为了给后续的参数传递值,我们只能使用按名称匹配的方法。
六、”**“参数只能出现在最后一个形参之后
想想为什么?其实很好理解,因为出现在”**“形参之后的形参,无论使用按顺序传递还是按名称传递,最终都无法到达参数值真正应该需要到的地方。所以python规定,如果需要”**“参数,那它必须是最后一个形参。否则python会报语法错误。
七、函数调用中的”*“
在表格中我们看到了有func(*iteratable)的调用,这个调用的意思是,iteratable必须是一个可迭代的容器,比如list、tuple;作为参数传递值,它最终传递到函数时,不是以一个整体出现,而是将其中的元素按照顺序传递的方式,一次赋值给函数的形参。例如,
li = ['rechar', 27]
func(*li)
这个函数调用与
func('rechar', 27)
是等价的。
八、函数调用中的”**“
知道”*“在函数调用中的效果之后,也就很好理解”**“的作用了。它是将传递进来的dict对象分解,每一个元素对应一个按名称传递的参数,根据其中的key对参数进行赋值。
match从字符串的开头开始匹配,
search是从字符串任意位置开始匹配,
上面两个都是匹配上一个就停止。
还有findall是返回所有能匹配上的字符串列表。
你可以敲敲下面这些代码自己体会一下
12345678import retext = 'c++ python2 python3 perl ruby lua java javascript php4 php5 c'#match,search,findall,split,subre.match(r'c++',text)re.match(r'c\+\+',text)re.match(r'java',text)re.search(r'java',text)print re.findall(r'python',text)
建议使用以下正则表达式:
(?=)[^a-zA-Z0-9_]+(?=)
前面的 (?=) 和后面的 (?=) ,使得匹配出现在 . . . 之间;
[^a-zA-Z0-9_]+ 排除对英文数字下划线的匹配,可根据具体情况作变动。