1

I have a string s="expences > drinks" that is sent to a function. Inside that function I am supposed to add new values using raw_input() till I input an empty string.

Each one of these inputs should be added to the initial string. In the case of an empty string, the function must return the string with all of the previously added words.

I tried to realize it by calling the function from itself and pass it the changed string but it just returns with only the first added word. I also tried avoid calling the function from itself using while True: and if empty string then break the loop and return the value. But none of these variants works properly.

Please explain what I do wrong and what is the most pythonic way of doing this.

Here's the code:

#!/usr/bin/env python -tt
# -*- coding: utf-8 -*-

def create_sub_cat(parent):     
    print "creating subcat\n %s > " %(parent)
    conf=raw_input("type new subcat or press \"ENTER\" to save changes\n")
    if conf!="":
        parent+=" > "+conf
        create_sub_cat(parent)
    return parent

s="expences  > drinks"
print create_sub_cat(s)
Greenonline
  • 1,330
  • 8
  • 23
  • 31
Sergii Artele
  • 63
  • 1
  • 11
  • 2
    Well, you're not doing anything with the return value when you call the function recursively. You're neither `return`ing its result nor are you otherwise using it. – deceze May 10 '15 at 09:53

1 Answers1

1

You can use iter with a for loop, you don't need to keep calling the function, iter takes a sentinel value as it's last arg which it will keep looping until the sentinel value is entered:

def create_sub_cat(parent):
    print "creating subcat\n {} > ".format(parent)
    for conf in iter(lambda: raw_input("type new subcat or"
                                       " press \"ENTER\" to save changes\n"),""): # empty string for sentinel value
        parent += " > " + conf
    return parent

Or using a while True:

def create_sub_cat(parent):
    print "creating subcat\n {} > ".format(parent)
    while True:
        conf = raw_input("type new subcat or"
                                       " press \"ENTER\" to save changes\n")
        if not conf: # if user enters empty string break
            break
        parent +=" > " + conf # else keep concatenating
    return parent

Why your code does not work is because you don't return the recursive calls so you only get the first value:

def create_sub_cat(parent):
    print "creating subcat\n %s > " %(parent)
    conf=raw_input("type new subcat or press \"ENTER\" to save changes\n")
    if conf!="":
        parent+=" > "+conf
        return create_sub_cat(parent) # return 
    return parent
Padraic Cunningham
  • 176,452
  • 29
  • 245
  • 321
  • Ok, thanks. And which one of these solutions is better? – Sergii Artele May 10 '15 at 10:29
  • @SergiiArtele, I prefer the `iter` approach but it comes down to personal preference really between iter and the while. Both would be preferential to the recursive approach. If I am casting input to int, float.. I would use a while with a try/except but just just taking input I prefer the iter. – Padraic Cunningham May 10 '15 at 10:31
  • @PadraicCunningham In my opinion, using a nested function instead of the lambda would make it a bit more readable. You could add a proper docstring to the helper function. Furthermore, a short function name would make the sentinel more obvious. Now it is rather hard to pick up a the end of the long lambda line. – Mike Müller May 10 '15 at 11:05