Python: проверьте, является ли объект списком строк

Как проверить, является ли объект списком строк? Я мог только проверить, является ли объект строкой как таковой:

def checktype(obj):
  if isinstance(obj,str):
    print "It a string"

obj1 = ['foo','bar','bar','black','sheet']
obj2 = [1,2,3,4,5,'bar']
obj3 = 'bar'

for i in [obj1,obj2,obj3]:
  checktype(i)

Требуемый вывод:

It a list of strings
It not a list of strings or a single string
It a single string

Ответ 1

Что-то вроде этого, я полагаю? Вы можете сделать несколько проверок, чтобы убедиться, что это одна строка.

>>> def checktype(obj):
        return bool(obj) and all(isinstance(elem, basestring) for elem in obj)

>>> obj1 = ['foo','bar','bar','black','sheet']
>>> obj2 = [1,2,3,4,5,'bar']
>>> obj3 = 'bar'
>>> for i in [obj1, obj2, obj3] :
        print checktype(i)


True
False
True

Зачем проверять basestring вместо str?

Вы должны проверить basestring вместо str, так как это общий класс, из которого наследуются типы str и unicode. Проверка только str не учитывает типы unicode.

Согласно рекомендациям Стивена Румбальского, если вам нужно специально проверить список строк, вы могли бы сделать.

>>> def is_list_of_strings(lst):
        return bool(lst) and not isinstance(lst, basestring) and all(isinstance(elem, basestring) for elem in lst)
        # You could break it down into `if-else` constructs to make it clearer to read.

>>> for i in [obj1, obj2, obj3] :
        print is_list_of_strings(i)


True
False
False

EDIT. В соответствии с предложением abarnert вы также можете проверить list вместо not isinstance(lst, basestring), код получит переписан как.

>>> def is_list_of_strings(lst):
        return bool(lst) and isinstance(lst, list) and all(isinstance(elem, basestring) for elem in lst)
        # You could break it down into `if-else` constructs to make it clearer to read.

>>> for i in [obj1, obj2, obj3] :
        print is_list_of_strings(i)


True
False
False

Отступая от одного лайнера, мы могли бы использовать.

>>> def is_list_of_strings(lst):
        if lst and isinstance(lst, list):
            return all(isinstance(elem, basestring) for elem in lst)
        else:
            return False

Ответ 2

Чтобы проверить, являются ли все элементы в списке строками, используйте встроенные all и генератор:

if all(isinstance(s, str) for s in lis):

Обратите внимание, что если ваш список пуст, он все равно вернет True поскольку это технически список из 0 строк. Однако, так как вы хотите считать [] False, вам нужно сделать это:

if lis and all(isinstance(s, str) for s in lis):

Итак, ваша функция должна выглядеть примерно так:

def checktype(obj):
    # This if statement makes sure input is a list that is not empty
    if obj and isinstance(obj, list): 
        return all(isinstance(s, str) for s in obj)
    else:
        return False

Эта функция будет возвращать True только в том случае, если ее входные данные являются непустым списком и полностью состоят из строк. Все остальное (например, [], ['a', 1], ('a', 'b') и т.д.) Вернет значение False.

Кроме того, использование all таким образом имеет дополнительный бонус в том, что он прекращает проверку первого найденного элемента, который возвращает False (не является строкой). Это позволяет довольно эффективно работать с очень большими списками.

Ответ 3

Ответы, которые я читал до сих пор, вызывают исключения, если вам предоставляется не-список, который не является строкой... и не является итерабельным. Этот вопрос решается в:

В Python, как определить, является ли объект итерируемым?

Принимая подход к настройке утки:

def categorize(x):
    result = "not a string or list of strings"
    if isinstance(x, basestring):
        return "It a single string"
    try:
        if all(isinstance(y, basestring) for y in x):
            return "It a list of strings"
    except TypeError:
        pass
    return "It not a list of strings or a single string"

data = [ 5, "xyzzy", list("xyzzy"), ['1', '23', 456]]
for x in data:
    print x, categorize(x)

Вывод:

5 It not a list of strings or a single string
xyzzy It a single string
['x', 'y', 'z', 'z', 'y'] It a list of strings
['1', '23', 456] It not a list of strings or a single string

Ответ 4

Этот ответ для Python 3. Если, например, имя переменной pins:

if not (pins and isinstance(pins, list) and all(isinstance(pin, str) for pin in pins)):
    raise TypeError('pins must be a list of one or more strings.')

Он проверяет три вещи:

  1. Это не пусто?
  2. Это список?
  3. Содержит ли он строки?

Если вам также необходимо проверить уникальность строк, включите эту четвертую проверку:

and (len(tokens) == len(set(tokens)))