使用Python计算字符串中大写字母的数量

46

我正在尝试找出如何计算字符串中大写字母的数量。

我只能计算小写字母:

def n_lower_chars(string):
    return sum(map(str.islower, string))

我试图完成的示例:

Type word: HeLLo                                        
Capital Letters: 3

当我尝试翻转上面的函数时,它会产生错误:

def n_upper_chars(string):
    return sum(map(str.isupper, string))

1
重新阅读这个问题,我没有看到sum(map(str.isupper, string))不起作用的任何理由。 - njzk2
1
问题中的代码有效,至少在Python 3.9中是这样。 - SwimBikeRun
8个回答

78
你可以使用 sum,一个 生成器表达式str.isupper 来实现这个功能:
message = input("Type word: ")

print("Capital Letters: ", sum(1 for c in message if c.isupper()))

请参见下面的演示:

>>> message = input("Type word: ")
Type word: aBcDeFg
>>> print("Capital Letters: ", sum(1 for c in message if c.isupper()))
Capital Letters:  3
>>>

不错!但是 sum(1 for x in message if x.isupper() ) 怎么样?我知道 True 是 '1',但是用整数而不是布尔值求和似乎更优雅,不是吗? - dani herrera
1
是的 - 我也会选择 (sum 1 for x... 的方法,以使其明确,而不是依赖于布尔值具有0/1整数值的性质(由于历史原因)。 - Jon Clements
一个相关的形式:sum(c in string.uppercase for c in message) - Winny

16
你可以使用re
import re
string = "Not mAnY Capital Letters"
len(re.findall(r'[A-Z]',string))

5


13

使用lenfilter

import string
value = "HeLLo Capital Letters"
len(filter(lambda x: x in string.uppercase, value))
>>> 5

8

我对上述方法进行了比较,同时采用了使用Python 3.7.4编译的正则表达式。
为此,我使用了Lewis Carroll的作品《爱丽丝漫游奇境记》(来自项目古腾堡)。

from urllib.request import urlopen

# Download 
text = urlopen('https://www.gutenberg.org/files/11/11-0.txt').read().decode('utf-8')
# Split it into the separate chapters and remove table of contents, etc
sep = 'CHAPTER'
chaps = [sep + ch for ch in text.split('CHAPTER') if len(ch) > 1000]
len(chaps)

将所有方法定义为函数,以便在循环中使用并保持简洁。

import re
import string

def py_isupper(text): 
    return sum(1 for c in text if c.isupper())

def py_str_uppercase(text):
    return sum(1 for c in text if c in string.ascii_uppercase)

def py_filter_lambda(text):
    return len(list(filter(lambda x: x in string.ascii_uppercase, text)))

def regex(text):
    return len(re.findall(r'[A-Z]',text))

# remove compile from the loop
REGEX = re.compile(r'[A-Z]')
def regex_compiled(text):
    return len(REGEX.findall(text))
以下是结果。
%%timeit
cnt = [py_isupper(ch) for ch in chaps]
每次循环的平均耗时为 7.84 毫秒,标准差为 69.7 微秒,总共运行了 7 次,每次循环执行了 100 次。
%%timeit
cnt = [py_str_uppercase(ch) for ch in chaps]
11.9毫秒± 94.6微秒每个循环(平均值± 7次运行的标准差,每个循环100次)
%%timeit
cnt = [py_filter_lambda(ch) for ch in chaps]

19.1毫秒±499微秒每次循环(平均值±7次运行的标准偏差,每个循环100次)

%%timeit
cnt = [regex(ch) for ch in chaps]
每次循环的平均值为1.49毫秒±13微秒,共运行7次,每次运行1000次。
%%timeit
cnt = [regex_compiled(ch) for ch in chaps]
每个循环的平均时间为1.45毫秒,标准偏差为8.69微秒(7次运行,每次1000个循环)。

4
from string import ascii_uppercase
count = len([letter for letter in instring if letter in ascii_uppercase])

这不是最快的方法,但我喜欢它易读性强的特点。另一种方法是不使用导入字符串,并采用类似的语法:

count = len([letter for letter in instring if letter.isupper()])

我同意。这样我就可以看到发生了什么。 - Stevenson
@Stevenson 如果你觉得更易读,也可以使用 uppercase 替代 ascii_uppercase。你可以在这里了解两者之间的区别:http://docs.python.org/2/library/string.html#string-constants。 - mr2ert
太棒了!这让我更好地理解了。很棒的链接。 - Stevenson

3
def n_lower_chars(string):
    return sum(i.isupper() for i in string)

该生成器表达式中 True 值的总和


1
这个有效。
s = raw_input().strip()
count = 1
for i in s:
    if i.isupper():
        count = count + 1
print count

0

这个问题的(稍微)最快方法似乎是在一个frozenset中进行成员测试

import string
message='FoObarFOOBARfoobarfooBArfoobAR'
s_upper=frozenset(string.uppercase)

%timeit sum(1 for c in message if c.isupper())
>>> 100000 loops, best of 3: 5.75 us per loop

%timeit sum(1 for c in message if c in s_upper)
>>> 100000 loops, best of 3: 4.42 us per loop

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,