我试图将一个任意长度的字符串拆分为3个字符的块。 我知道这个问题之前已经被问到过了( 你如何将一个列表分成均匀大小的块? ),但是这个答案通过列表理解来解决问题; 我试图用递归函数调用来解决这个问题,所以我的问题更多的是关于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)I am trying to split a string of arbitrary length into chunks of 3 characters. I know this question has been asked previously (How do you split a list into evenly sized chunks?), but that answer solves the problem with a list comprehension; I'm trying to solve the problem using a recursive function call, so my question is more about recursive functions calls in Python.
My function works fine until the "base case", the very last string of 3 or less characters. I am getting a TypeError: can only concatenate list (not "NoneType") to list.
Why is the base case returning None instead of a list? I explicitly create a list called final_value in the base case and return that. I even have a debugging print statement that shows me that the base case return value is of type <class 'list'>.
My code is below.
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)最满意答案
你有两个问题:
你只 return基本情况,所以其他情况会隐含return None ; 和
您不要在基本情况下改变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']这种方法的缺点是它创建了几个列表。 如果您希望每个顶级呼叫都有一个列表,您可以执行以下操作:
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 ,请参阅“最小惊讶”和可变默认参数 。
You have two problems:
You only return in the base case, so the other case will implicitly return None; and
You don't mutate three_char_strings in the base case. In fact, it's not clear why you would implement this to mutate an external list at all, as this will cause problems if you need to call it again.
You should probably have done something like:
def split3(str): if len(str) <= 3: return [str] else: beginning = str[:3] remaining = str[3:] return [beginning] + split3(remaining)Which does what you want, without relying on the three_char_list list to be in-scope and empty when the function is called:
>>> split3('abcdefghijklmnopqrstuvwxyz') ['abc', 'def', 'ghi', 'jkl', 'mno', 'pqr', 'stu', 'vwx', 'yz']The downside of that approach is that it creates several lists. If you want one list per top-level call, you could do e.g.:
def split3(str, out=None): if out is None: out = [] out.append(str[:3]) if len(str) > 3: split3(str[3:], out) return outIf you're wondering why out=None, see "Least Astonishment" and the Mutable Default Argument.
更多推荐
发布评论