Personal archive tool, looking for suggestions on improving the code

Peter Otten __peter__ at web.de
Tue Jul 27 08:06:34 EDT 2010


mo reina wrote:

> On 27 Lug, 10:23, Peter Otten <__pete... at web.de> wrote:
>> mo reina wrote:
>> > i've written a tool in python where you enter a title, content, then
>> > tags, and the entry is then saved in a pickle file. it was mainly
>> > designed for copy-paste functionality (you spot a piece of code you
>> > like on the net, copy it, and paste it into the program), not really
>> > for handwritten content, though it does that with no problem.
>>
>> > i mainly did it because i'm always scanning through my pdf files,
>> > books, or the net for some coding example of solution that i'd already
>> > seen before, and it just seemed logical to have something where you
>> > could just put the content in, give it a title and tags, and just look
>> > it up whenever you needed to.
>>
>> > i realize there are sites online that handle this ex.
>> >http://snippets.dzone.com, but i'm not always online when i code. i also
>> > admit that i didn't really look to see if anyone had written a desktop
>> > app, the project seemed like a fun thing to do so here i am.
>>
>> > it wasn't designed with millions of entries in mind, so i just use a
>> > pickle file to serialize the data instead of one of the database APIs.
>> > the query is also very basic, only title and tags and no ranking based
>> > on the query.
>>
>> > there is an issue that i can't figure out, when you are at the list of
>> > entries there's a try, except clause where it tries to catch a valid
>> > index (integer). if you enter an inavlid integer, it will ask you to
>> > enter a valid one, but it doesn't seem to be able to assign it to the
>> > variable. if you enter a valid integer straightaway, there are no
>> > problems and the entry will display.
>>
>> > anyway let me know what you guys think. this is coded for python3.
>> > def choices(list_result):
>> > '''takes a list of objects and returns the index of the selected
>> > object'''
>> > os.system('clear')
>> > index = 0
>> > for entry in list_result:
>> > print('{}. {}'.format(index, entry.title))
>> > index += 1
>> > try:
>> > choice = int(input('\nEnter choice: '))
>> > return choice
>> > except:
>> > pause = input('\nplease enter a valid choice')
>> > choices(list_result)
>>
>> When the exception is triggered you call choices() recursively but
>> discard the result. Therefore you get Python's default, None, which is
>> not a valid index. Change the last line to
>>
>> return choices(list_result)
>>
>> for a minimal fix. However, I suggest that you use a while loop instead
>> of the recursion:
>>
>> def choices(list_result):
>> while True:
>> os.system('clear')
>> for index, entry in enumerate(list_result):
>> print('{}. {}'.format(index, entry.title))
>> try:
>> choice = int(input('\nEnter choice: '))
>> if 0 <= choice < len(list_result):
>> return choice
>> except ValueError:
>> pass
>> input('\nplease enter a valid choice')
>>
>> I've also added a test for the integer range and replaced the bare except
>> with a more specific one. I recommend that you never use bare excepts
>> because they can hide unexpected exceptions and lead to nasty bugs.
>>
>> You should also remove the recursive call of main(). Its only effect is
>> that when you enter an invalid choice twice you will have to enter "5"
>> twice to really exit your script.
>>
>> Peter
> 
> hi peter, i noticed the issue you mentioned but don't understand why
> they happen.
> 
> for example, when the function is called in the case of an exception,
> the variable choice is re-assigned to whatever the next input is, so
> why is the default None assigned instead?  and what' s the difference
> between just calling the function again (the variable list_result
> remains unchanged) and using a return statement?

If you have a function

def f():
    return 42

and just call it from another function

def g():
    f()

the result of f() is evaluated but immediately discarded. If you want to use 
it inside g() you have to assign it to a variable

def g():
    x = f()
    y = x * x
    print y

and if you want to use it outside g() you can return it. 

def g():
   return f()

For recursion the same rules apply, only with the same function as f and g.
Here's a simple example for you to work out the program flow:

>>> def r1(n):
...     print "entering level", n
...     if n == 5:
...             print "limit reached"
...             print "exiting level", n
...             print "returning 42"
...             return 42
...     else:
...             print "recursing"
...             r1(n+1)
...     print "exiting level", n
...     print "(implicitly) returning None"
...
>>> r1(0)
entering level 0
recursing
entering level 1
recursing
entering level 2
recursing
entering level 3
recursing
entering level 4
recursing
entering level 5
limit reached
exiting level 5
returning 42
exiting level 4
(implicitly) returning None
exiting level 3
(implicitly) returning None
exiting level 2
(implicitly) returning None
exiting level 1
(implicitly) returning None
exiting level 0
(implicitly) returning None

Try to change r1() to return the value from the innermost call (i. e. 42) to 
the outside world. Once you have understood what is going on you should be 
able to see what's wrong with your program.

Peter



More information about the Python-list mailing list