2012-07-14 100 views
2

我正在编写一个经验和知识的搜索引擎。目前,我正在构建一个爬行器及其附带的实用程序。其中之一是URL规范化器。这就是我现在想要构建的内容,更具体地说,我被困在了一个地方,那就是我必须制作一个方法来获得一个url,并且使用一个'%'符号后的字母大写。我的代码到目前为止:为什么这段代码无限循环?

def escape_sequence_capitalization(url): 
     ''' The method that capitalizes letters in escape sequences. 
     All letters within a percent - encoding triplet (e.g. '%2C') are case 
     insensitive and should be capitalized. 

     ''' 
    next_encounter = None 
    url_list = [] 
    while True: 
     next_encounter = url.find('%') 
     if next_encounter == -1: 
      break 

     for letter in url[:next_encounter]: 
      url_list.append(letter) 

     new_character = url[next_encounter + 1].upper() 
     url_list.append(new_character) 
     url = url[next_encounter:] 

    for letter in url: 
     url_list.append(letter) 

    return ''.join(url_list) 

有人可以指导我,我的错误是哪里?我会很感激。谢谢。

编辑:这就是我想实现:

http://www.example.com/a%c2%b1b → http://www.example.com/a%C2%B1b 

回答

10

通过静态分析,它会永久循环,因为您的while True永远不会中断。那么它在哪里可以突破?仅当next_encounter等于-1时才在break声明中;所以你可以推断它永远不会。

为什么不呢?在url.find之后尝试print next_encounter。你很快就会看到,

url = url[next_encounter:] 

做你希望几乎什么会,只是它给你一个角色比你希望的。

为什么我以这种方式呈现?主要是因为学习语言的人往往低估了print的价值。

+0

谢谢你,你的回答是最有见地的。我并不低估print()的价值,打印方法和函数是我在其他编程语言中使用的主要调试工具,它只是因为我缺乏经验而没有引起我的注意。谢谢。 – NlightNFotis 2012-07-14 18:24:05

+0

@msw。很好的解释! – doniyor 2012-07-14 18:25:37

3

这就是为什么:

>>> 'asd'.find('s') 
1 
>>> 'asd'[1:] 
'sd' 

而且,考虑使用第二个参数str.find()而不是切片。

4

@msw钉了它,并给出了合理的建议。

我的$ .02是你永远不应该尝试这个循环

如何:

>>> re.sub('%..',lambda m: m.group(0).upper(),'http://www.example.com/a%c2%b1b') 
'http://www.example.com/a%C2%B1b' 
+0

听起来像一个计划,但我是一个Python新手,目前lambda对我来说有点困惑,所以如果我能避免它们,我宁愿这样做。 – NlightNFotis 2012-07-14 18:37:19

+3

lambda不过是一行功能。可能已经在[docs for're]中创建了一个函数。sub'](http://docs.python.org/library/re.html)。拥抱功能范式。抵抗是徒劳的。 – 2012-07-14 18:47:35

+2

Lol'd'拥抱功能范式。抵抗是徒劳的。'部分。很好的一个伴侣。 – NlightNFotis 2012-07-14 18:54:26

1

我来了有点迟到了,但你可能要考虑使用常规表达,而不是这样的复杂功能:

>>> import re 
>>> url = "http://www.example.com/a%c2%b1b" 
>>> result = re.sub("(?i)%[0-9A-F]{2}", lambda x: x.group(0).upper(), url) 
>>> result 
'http://www.example.com/a%C2%B1b' 

说明:

(?i)   # Make regex case-insensitive 
%    # Match a % 
[0-9A-F]{2} # Match two hex digits 

re.sub()找到字符串在所有这些出现并将结果(匹配对象的group(0))到.upper()方法,然后替换原来的与所述匹配的大写的版本。

+0

很好的回答。会考虑你的方法。 – NlightNFotis 2012-07-15 09:44:59