Python,更智能的字符串转整数方法
我写了这段代码,用来把格式像“0(532) 222 22 22”的字符串转换成整数,比如05322222222。
class Phone():
def __init__(self,input):
self.phone = input
def __str__(self):
return self.phone
#convert to integer.
def to_int(self):
return int((self.phone).replace(" ","").replace("(","").replace(")",""))
test = Phone("0(532) 222 22 22")
print test.to_int()
我觉得用三个替换方法来解决这个问题有点笨拙。我想知道有没有更好的办法?
4 个回答
那就直接用正则表达式怎么样?
举个例子:
>>> import re
>>> num = '0(532) 222 22 22'
>>> re.sub('[\D]', '', num) # Match all non-digits ([\D]), replace them with empty string, where found in the `num` variable.
'05322222222'
ChristopheD 提出的建议是可以用的,但效率没有那么高。
下面是一个测试程序,用来展示如何使用 dis 模块(想了解更多详细信息,可以查看 Doug Hellman 的 PyMOTW 里关于这个模块的内容,链接在这里)。
TEST_PHONE_NUM = '0(532) 222 22 22'
def replace_method():
print (TEST_PHONE_NUM).replace(" ","").replace("(","").replace(")","")
def list_comp_is_digit_method():
print ''.join([x for x in TEST_PHONE_NUM if x.isdigit()])
def translate_method():
print (TEST_PHONE_NUM).translate(None,' ()')
import re
def regex_method():
print re.sub('[\D]', '', TEST_PHONE_NUM)
if __name__ == '__main__':
from dis import dis
print 'replace_method:'
dis(replace_method)
print
print
print 'list_comp_is_digit_method:'
dis(list_comp_is_digit_method)
print
print
print 'translate_method:'
dis(translate_method)
print
print
print "regex_method:"
dis(phone_digit_strip_regex)
print
输出结果:
replace_method:
5 0 LOAD_GLOBAL 0 (TEST_PHONE_NUM)
3 LOAD_ATTR 1 (replace)
6 LOAD_CONST 1 (' ')
9 LOAD_CONST 2 ('')
12 CALL_FUNCTION 2
15 LOAD_ATTR 1 (replace)
18 LOAD_CONST 3 ('(')
21 LOAD_CONST 2 ('')
24 CALL_FUNCTION 2
27 LOAD_ATTR 1 (replace)
30 LOAD_CONST 4 (')')
33 LOAD_CONST 2 ('')
36 CALL_FUNCTION 2
39 PRINT_ITEM
40 PRINT_NEWLINE
41 LOAD_CONST 0 (None)
44 RETURN_VALUE
phone_digit_strip_list_comp:
3 0 LOAD_CONST 1 ('0(532) 222 22 22')
3 STORE_FAST 0 (phone)
4 6 LOAD_CONST 2 ('')
9 LOAD_ATTR 0 (join)
12 BUILD_LIST 0
15 DUP_TOP
16 STORE_FAST 1 (_[1])
19 LOAD_GLOBAL 1 (test_phone_num)
22 GET_ITER
23 FOR_ITER 30 (to 56)
26 STORE_FAST 2 (x)
29 LOAD_FAST 2 (x)
32 LOAD_ATTR 2 (isdigit)
35 CALL_FUNCTION 0
38 JUMP_IF_FALSE 11 (to 52)
41 POP_TOP
42 LOAD_FAST 1 (_[1])
45 LOAD_FAST 2 (x)
48 LIST_APPEND
49 JUMP_ABSOLUTE 23
52 POP_TOP
53 JUMP_ABSOLUTE 23
56 DELETE_FAST 1 (_[1])
59 CALL_FUNCTION 1
62 PRINT_ITEM
63 PRINT_NEWLINE
64 LOAD_CONST 0 (None)
67 RETURN_VALUE
translate_method:
11 0 LOAD_GLOBAL 0 (TEST_PHONE_NUM)
3 LOAD_ATTR 1 (translate)
6 LOAD_CONST 0 (None)
9 LOAD_CONST 1 (' ()')
12 CALL_FUNCTION 2
15 PRINT_ITEM
16 PRINT_NEWLINE
17 LOAD_CONST 0 (None)
20 RETURN_VALUE
phone_digit_strip_regex:
8 0 LOAD_CONST 1 ('0(532) 222 22 22')
3 STORE_FAST 0 (phone)
9 6 LOAD_GLOBAL 0 (re)
9 LOAD_ATTR 1 (sub)
12 LOAD_CONST 2 ('[\\D]')
15 LOAD_CONST 3 ('')
18 LOAD_GLOBAL 2 (test_phone_num)
21 CALL_FUNCTION 3
24 PRINT_ITEM
25 PRINT_NEWLINE
26 LOAD_CONST 0 (None)
29 RETURN_VALUE
translate 方法是最有效率的,不过需要 Python 2.6 以上的版本。正则表达式的效率稍微低一点,但兼容性更好(我觉得这对你来说很重要)。而原来的 replace 方法每替换一次会多加 6 条指令,而其他方法则保持不变。
顺便提一下,存储电话号码时最好用字符串格式,这样可以处理前面的零,并在需要的时候使用电话格式化工具。相信我,这个问题我之前遇到过。
在Python 2.6或2.7中,
(self.phone).translate(None,' ()')
这段代码会把电话号码中的空格、左括号(
和右括号)
都去掉。想了解更多,可以查看Python 2.6的文档。
而在Python 3.x中,str.translate()方法需要一个映射(而不是像上面那样的两个字符串)。所以对应的代码大概是这样的,使用str.maketrans()来生成这个映射。
'(self.phone).translate(str.maketrans('','', '()-/ '))
想了解更多,可以查看Python 3.1的文档。
p = "0(532) 222 22 22"
print ''.join([x for x in p if x.isdigit()])
注意,如果你想把它转换成整数(就像你在标题中提到的那样),你会“丢失”前面的零。如果你想这么做,只需把上面的内容放在一个 int()
的调用里。不过,我觉得电话号码作为字符串更合适。