2015-02-17 3 views
1

Я пытаюсь разбить строку произвольной длины на куски из 3 символов. Я знаю, что этот вопрос задан ранее (How do you split a list into evenly sized chunks?), но этот ответ решает проблему с пониманием списка; Я пытаюсь решить проблему, используя вызов рекурсивной функции, поэтому мой вопрос связан скорее с вызовами рекурсивных функций в Python.Разбиение строки на куски с использованием рекурсии

Моя функция отлично работает до «базового футляра», самой последней строки из 3 или менее символов. Я получаю TypeError: can only concatenate list (not "NoneType") to list.

Почему основной корпус возвращает None вместо list? Я явно создаю список с именем final_value в базовом футляре и верну его. У меня даже есть отладочная заявка на печать, которая показывает мне, что возвращаемое базовое значение имеет тип <class 'list'>.

Мой код ниже.

three_char_strings = [] 

def split3(str): 
    if len(str) <= 3: 
     final_value = [] 
     final_value.append(str) 
     print('Final value: %s\nFinal value type: %s\n' % (final_value, type(final_value))) #For debugging 
     return final_value 
    else: 
     beginning = str[0:3] 
     three_char_strings.append(beginning) 
     remaining = str[3:] 
     three_char_strings + split3(remaining) 
+0

Ваша рекурсивная функция только на самом деле 'return' в базовом случае - это нужно сделать в обоих. – jonrsharpe

+0

Да, я вижу это сейчас, и мне нужно это исправить. Спасибо. Но это все еще не устраняет проблему, почему базовый случай возвращает «NoneType». – LeonardShelby

+1

В базовом случае нет, ** другой случай - ** (без явного «возврата» вы по умолчанию получаете «Нет»). – jonrsharpe

ответ

3

у вас есть две проблемы:

  1. You толькоreturn в базе с ase, поэтому другой случай будет неявно return None; и

  2. Вы не мутируете three_char_strings в базовом корпусе. На самом деле, непонятно, почему вы должны реализовать это, чтобы изменить внешний список на всех, так как это вызовет проблемы, если вам нужно снова позвонить ему.

Вы должны, вероятно, сделать что-то вроде:

def split3(str): 
    if len(str) <= 3: 
     return [str] 
    else: 
     beginning = str[:3] 
     remaining = str[3:] 
     return [beginning] + split3(remaining) 

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

>>> split3('abcdefghijklmnopqrstuvwxyz') 
['abc', 'def', 'ghi', 'jkl', 'mno', 'pqr', 'stu', 'vwx', 'yz'] 

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

def split3(str, out=None): 
    if out is None: 
     out = [] 
    out.append(str[:3]) 
    if len(str) > 3: 
     split3(str[3:], out) 
    return out 

Если вам интересно, почему out=None см "Least Astonishment" and the Mutable Default Argument.

+0

Спасибо. Я не мог понять, как это сделать без глобального списка. Я просто не знал достаточно. Теперь я это делаю. Спасибо. – LeonardShelby

2

Хотя первоначальный вопрос в том, что ваш, не базовый случай не имел return заявление (это означает, что неявно возвращается None), это также полезно увидеть, как код может быть упрощен в Python

def split3(s): 
    return [s] if len(s) <= 3 else [s[:3]] + split3(s[3:]) 
+0

Спасибо, г-н Ф. Это более элегантное решение на языке Pythonic, и я буду использовать его в будущем. Я не проверял ваш ответ как «ответ», потому что я действительно хотел попасть в сорняки своей рекурсивной функции. – LeonardShelby

Смежные вопросы