Я хочу знать, все ли слова в списке написаны заглавными буквами, то есть все буквенные символы написаны заглавными буквами.

Я пробовал это для простой строки, чтобы понять поведение isupper():

>>> 'FDSFS BBIBIFBIBWEF ASDASD 112,32:/'.isupper()    
True

Поэтому я разделил слова в этом предложении на список:

>>> sent = ['FDSFS','BBIBIFBIBWEF','ASDASD', '112','32:/']
>>> all([word.isupper() for word in sent])
False

Итак, я проверил список аргументов для all():

>>> [word.isupper() for word in sent]
[True, True, True, False, False]

Как ни странно, isupper() возвращает False для строк, не содержащих алфавитов (состоящих только из чисел и специальных символов), но возвращает True, если эти строки содержат хотя бы один заглавный символ. :

>>> '123'.isupper()
False
>>> '123A'.isupper()
True
>>> '123?A'.isupper()
True
>>> '123?'.isupper()
False
>>> ''.isupper()
False

Q1. Есть ли какое-либо дизайнерское решение, стоящее за таким поведением для isupper()?
Q2. Как я могу достичь того, что я хочу, самым питоническим и минимальным способом? (Может быть, есть какая-то другая функция, которая просто проверяет, все ли алфавитные слова во входной строке заглавные, и вообще не заботится о специальных символах, числах и пустых строках? Или мне нужно написать их с нуля?)

3
Mahesha999 10 Окт 2021 в 12:06

3 ответа

Лучший ответ

Q1 :

Как упоминалось в документации:

Вернуть True, если все символы в регистре в строке прописные и есть хотя бы один регистр, иначе False.

Как видите, он проверяет, все ли символы в строке являются прописными, а не только буквы.

Это похожая реализация:

import string
def upper(s):
    return all([word in string.ascii_uppercase for word in s])

Q2 :

Решение 1.

Чтобы решить эту проблему, можно использовать upper и проверить, эквивалентна ли она исходной строке:

>>> sent = ['FDSFS','BBIBIFBIBWEF','ASDASD', '112','32:/']
>>> all([word.upper() == word for word in sent])
True
>>> 

Решение 2:

Или проверьте, не является ли ни один из символов строчными буквами:

>>> sent = ['FDSFS','BBIBIFBIBWEF','ASDASD', '112','32:/']
>>> all([(not word.islower()) for word in sent])
True
>>> 

Только что понял, что @DaniMesejo опубликовал это, спасибо ему.

Решение 3:

Это можно сделать очень элегантно и с регулярным выражением:

>>> import re
>>> sent = ['FDSFS','BBIBIFBIBWEF','ASDASD', '112','32:/']
>>> expr = re.compile('^[^a-z]*$')
>>> all(map(expr.search, sent))
True
>>> 

С map и скомпилированным регулярным выражением может быть более эффективным.

3
U12-Forward 10 Окт 2021 в 09:17

Используйте отрицание str.islower:

sent = ['FDSFS','BBIBIFBIBWEF','ASDASD', '112','32:/']
result = [(not word.islower()) for word in sent]
print(result)

Вывод

[True, True, True, True, True]

Поведение isupper объясняется в документации:

Верните True, если все символы в регистре в строке являются прописными и есть хотя бы один символ, заключенный в регистр, иначе - False.

(Акцент мой)

Обрезанный символ:

Символы в регистре - это символы с общим свойством категории, являющимся одним из следующих: «Lu» (буква, верхний регистр), «Ll» (буква, нижний регистр) или «Lt» (буква, регистр заголовка).

См. здесь для хорошее объяснение того, как идентифицировать символы, заключенные в регистр.

1
Dani Mesejo 10 Окт 2021 в 09:37

Если вы хотите увидеть, есть ли только верхние буквенные символы (минус пробел) , вы можете использовать регулярное выражение:

bool(re.match('[^A-Z\s]+', sent)

Или просто включите в чек str.isalpha:

sent.isupper() and sent.isalpha()
-1
Jab 10 Окт 2021 в 09:20