2013-08-28 2 views
9

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

def checktype(obj): 
    if isinstance(obj,str): 
    print "It's 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's a list of strings 
It's not a list of strings or a single string 
It's a single string 
+2

Для ясности я бы переименовать 'checktype' в' is_list_of_string'. –

+3

Один краевой случай для рассмотрения: '[]' список строк или нет? – abarnert

+0

nope '[]' не будет списком строки, это пустой список. – alvas

ответ

15

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

>>> 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.

В соответствии с предложениями Steven Rumbalski's, если вам нужно специально проверить список строк, вы могли бы сделать.

>>> 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's предложение, вы можете также проверить на 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 
+3

Спецификация говорит, чтобы проверить список * строк, поэтому 'checktype ('bar')' должен возвращать 'False'. Хорошая работа с использованием 'basestring'. –

+0

@StevenRumbalski: Исправлено. Спасибо за комментарий. :) –

+3

На самом деле, я думаю, было бы лучше проверить 'isinstance (lst, list)', чем 'not isinstance (lst, basestring)'. В конце концов, строки преобразования битов в строки не являются списком строк, а не строкой ... Но в остальном отличный ответ. – abarnert

13

Чтобы проверить, если все элементы списка являются строки, используйте 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 (не является строкой). Это позволяет работать с очень большими списками достаточно эффективно.

+2

Хороший ответ, но измените проверку экземпляра с 'str' на' basestr'. –

+2

... если, конечно, OP действительно не означало «list' of' str' », а не« список строк »... это возможно, но он не сказал, что он этого хочет. (@StevenRumbalski объясняет это довольно хорошо в своем ответе, поэтому я не думаю, что здесь необходимо объяснить это снова.) – abarnert

+0

Ну, я пошел с 'str', потому что в сообщении OP он проверял, был ли он типом' str', а не 'basestring'. – iCodez

2

ответы, которые я читал до сих пор поднять exepctions, когда данный неофициальный список, который не является строкой ... и не является итерацию либо.Этот вопрос рассматривается в:

In Python, how do I determine if an object is iterable?

Принимая утиного набрав подход:

def categorize(x): 
    result = "not a string or list of strings" 
    if isinstance(x, basestring): 
     return "It's a single string" 
    try: 
     if all(isinstance(y, basestring) for y in x): 
      return "It's a list of strings" 
    except TypeError: 
     pass 
    return "It's 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's not a list of strings or a single string 
xyzzy It's a single string 
['x', 'y', 'z', 'z', 'y'] It's a list of strings 
['1', '23', 456] It's not a list of strings or a single string 
Смежные вопросы