Как я могу сказать, является ли переменная python строкой или списком?



у меня есть процедура, которая принимает список строк в качестве параметра, но я хотел бы поддержать передачу в одной строке и преобразование ее в список одной строки. Например:



def func( files ):
for f in files:
doSomethingWithFile( f )

func( ['file1','file2','file3'] )

func( 'file1' ) # should be treated like ['file1']


как моя функция может определить, была ли передана строка или список? Я знаю, что есть type функция, но есть "более подходящие для Python" способ?

504   8  

8 ответов:

Ну,нет ничего необычного в проверке типа. Сказав это, если вы готовы положить небольшую нагрузку на абонента:

def func( *files ):
    for f in files:
         doSomethingWithFile( f )

func( *['file1','file2','file3'] ) #Is treated like func('file1','file2','file3')
func( 'file1' )

Я утверждаю, что это более подходящие для Python в том, что "явное лучше, чем неявное". Здесь есть, по крайней мере, признание со стороны вызывающего абонента, когда этот вход уже в виде списка.

isinstance(your_var, basestring)

лично мне не очень нравится такое поведение - оно мешает набирать утку. Можно утверждать, что он не подчиняется мантре "явное лучше, чем неявное". Почему бы не использовать синтаксис varargs:

def func( *files ):
    for f in files:
        doSomethingWithFile( f )

func( 'file1', 'file2', 'file3' )
func( 'file1' )
func( *listOfFiles )

Я бы сказал, что самый Python'y способ-заставить пользователя всегда передавать список, даже если в нем есть только один элемент. Это делает его действительно очевидным func() можно взять список файлов

def func(files):
    for cur_file in files:
        blah(cur_file)

func(['file1'])

как предложил Дэйв, вы можете использовать func(*files) синтаксис, но мне никогда не нравилась эта функция, и кажется более явным ("явное лучше, чем неявное"), чтобы просто потребовать список. Это также превращает ваш специальный случай (вызов func С одним файлом) в случае по умолчанию, потому что теперь вы должны использовать дополнительный синтаксис для вызова func С список..

если вы хотите сделать специальный случай для аргумента, являющегося строкой, используйте isinstance() builtin и сравните с basestring (который как str() и unicode() являются производными от) например:

def func(files):
    if isinstance(files, basestring):
        doSomethingWithASingleFile(files)
    else:
        for f in files:
            doSomethingWithFile(f)

действительно, я предлагаю просто требовать список, даже с одним файлом (в конце концов, он требует только двух дополнительных символов!)

def func(files):
    for f in files if not isinstance(files, basestring) else [files]:
        doSomethingWithFile(f)

func(['file1', 'file2', 'file3'])

func('file1')
if hasattr(f, 'lower'): print "I'm string like"

Если у вас есть больше контроля над абонентом, то один из других ответов лучше. У меня нет такой роскоши в моем случае, поэтому я остановился на следующем решении (с оговорками):

def islistlike(v):
   """Return True if v is a non-string sequence and is iterable. Note that
   not all objects with getitem() have the iterable attribute"""
   if hasattr(v, '__iter__') and not isinstance(v, basestring):
       return True
   else:
       #This will happen for most atomic types like numbers and strings
       return False

этот подход будет работать для случаев, когда вы имеете дело с знать список типов, которые отвечают вышеуказанным критериям. Однако некоторые типы последовательностей будут пропущены.

Varargs был запутанным для меня, поэтому я протестировал его на Python, чтобы очистить его для себя.

прежде всего PEP для varargs-это здесь.

вот пример программы, основанный на двух ответах от Дэйва и Дэвида Бергера, а затем вывод, просто для уточнения.

def func( *files ):
    print files
    for f in files:
        print( f )

if __name__ == '__main__':
    func( *['file1','file2','file3'] ) #Is treated like func('file1','file2','file3')
    func( 'onestring' )
    func( 'thing1','thing2','thing3' )
    func( ['stuff1','stuff2','stuff3'] )

и полученного результата;

('file1', 'file2', 'file3')
file1
file2
file3
('onestring',)
onestring
('thing1', 'thing2', 'thing3')
thing1
thing2
thing3
(['stuff1', 'stuff2', 'stuff3'],)
['stuff1', 'stuff2', 'stuff3']

надеюсь, что это полезно для кого-то еще.

Comments

    Ничего не найдено.