>>> s = 'AAAAAAAAAAAAAAAAAAA'
>>> s.count(s[0]) == len(s)
True
这不会进行短路运算。进行短路运算的版本如下:
>>> all(x == s[0] for x in s)
True
然而,由于C语言实现的优化,我有一种感觉,非短路版本在某些字符串上(取决于大小等因素)可能会表现得更好。
这里有一个简单的timeit
脚本,用于测试其他发布的选项:
import timeit
import re
def test_regex(s,regex=re.compile(r'^(.)\1*$')):
return bool(regex.match(s))
def test_all(s):
return all(x == s[0] for x in s)
def test_count(s):
return s.count(s[0]) == len(s)
def test_set(s):
return len(set(s)) == 1
def test_replace(s):
return not s.replace(s[0],'')
def test_translate(s):
return not s.translate(None,s[0])
def test_strmul(s):
return s == s[0]*len(s)
tests = ('test_all','test_count','test_set','test_replace','test_translate','test_strmul','test_regex')
print "WITH ALL EQUAL"
for test in tests:
print test, timeit.timeit('%s(s)'%test,'from __main__ import %s; s="AAAAAAAAAAAAAAAAA"'%test)
if globals()[test]("AAAAAAAAAAAAAAAAA") != True:
print globals()[test]("AAAAAAAAAAAAAAAAA")
raise AssertionError
print
print "WITH FIRST NON-EQUAL"
for test in tests:
print test, timeit.timeit('%s(s)'%test,'from __main__ import %s; s="FAAAAAAAAAAAAAAAA"'%test)
if globals()[test]("FAAAAAAAAAAAAAAAA") != False:
print globals()[test]("FAAAAAAAAAAAAAAAA")
raise AssertionError
在我的电脑上(OS-X 10.5.8,core2duo,python2.7.3)使用这些人工制造的(短)字符串,str.count
比set
和all
更快,并且比str.replace
稍微快一点,但被str.translate
和strmul
超过了,在这两者中,strmul
目前领先优势明显:
WITH ALL EQUAL
test_all 5.83863711357
test_count 0.947771072388
test_set 2.01028490067
test_replace 1.24682998657
test_translate 0.941282987595
test_strmul 0.629556179047
test_regex 2.52913498878
WITH FIRST NON-EQUAL
test_all 2.41147494316
test_count 0.942595005035
test_set 2.00480484962
test_replace 0.960338115692
test_translate 0.924381017685
test_strmul 0.622269153595
test_regex 1.36632800102
不同系统和不同字符串之间的时间可能会略有不同(甚至相差很大),因此值得使用实际要传递的字符串进行测试。
最终,如果在足够多的情况下达到了all
的最佳情况,并且你的字符串足够长,则可以考虑使用该算法。它是一种更好的算法...不过我会避免使用set
的解决方案,因为我没有看到任何它能够胜过count
解决方案的情况。
如果内存可能成为问题,那么就需要避免使用str.translate
、str.replace
和strmul
,因为这些会创建第二个字符串。但这通常不是一个问题。