Debbugging-For fixing a function - python

I am debugging the following function:
def buggy_dedup_sort_by_len(input):
unique = list(set(input))
return unique.sort(key=len)
the list is sorted but the unique.sort(key=len) is returning nothing.
wont the function list.sort return anything.How can I fix it???

sort returns None because it mutates the list in-place. Try:
def buggy_dedup_sort_by_len(input):
unique = list(set(input))
unique.sort(key=len)
return unique
Alternatively, use sorted, which does return a list.
def buggy_dedup_sort_by_len(input):
unique = list(set(input))
return sorted(unique, key=len)

Related

Return Inorder Traversal list

I'm trying to return list from inorder traversal and below is my code. If my input is [1,2,3] and output should be [3,1,2], but I'm returning value none. Can you please suggest what is wrong in my code? Thanks.
def inorderTraversal(currentNode,output=None):
if output==None:
output=[]
if currentNode.left:
return inorderTraversal(currentNode.left,output)
return output.append(currentNode.data)
if currentNode.right:
return inorderTraversal(currentNode.right,output)
The problem is this line:
return output.append(currentNode.data)
You are returning the value of append but that is None. append changes the list but it does not return the new value of the list. Do this instead.
output.append(currentNode.data)
return output

Using simple Recursion to create a list

I want every element in l(which is a list) to be added to a.
When I run the function, it gives me '[]' every time. How can I fix this?
def sim(l):
a = []
if len(l)>0:
a = a.append(l.pop())
l.pop()
return sim(l)
return a
Several things are wrong:
You shouldn't use lowercase L for a variable name - it looks like one
At the top of the function you assign an empty list to a - ultimately sim will be called with an empty list, then a will be assigned an empty list, the conditional statement will fail and sim will return an empty list.
Inside the conditional statement you assign the return value of list.append() to a. The return value is None so whatever a was before, it gets wiped out.
Inside the conditional statement you pop() two items out of your control list
An empty list has a boolean value of false so there is no need to explicitly check its length,
def sim(el, a = None):
if el:
a.append(el.pop())
return sim(el, a)
return a
I was taught to write the base case of a recursive function as the first statement:
def sim(el, a = None):
if not el:
return a
a.append(el.pop())
return sim(el, a)
append() doesn't return anything but does update the existing list. In other words, by trying to assign the result of the append() method, you're setting a to nothing after you have already appended the item.
Your Code :def sim(l):
a = []
when you call Function recursively return sim(l) every time it is call sim(l) and a=[] is empty.
Try This :
def sim(l,a):
if len(l)>0:
a.append(l.pop())
print a
return sim(l,a)
return a
Is this a homework assignment where you're required to do it in a certain (overly complicated) way? Because if not, you can add one list to another in Python like so:
>>> l = [1, 2, 3]
>>> a = []
>>> a.extend(l)
>>> a
[1, 2, 3]

Get list of data after recursion function

I need to run through db using recursion and get a list of results at the end. Function works correct (if print unrem) but I cann't return the list of results.
def find_locks(item, ids):
if item.video_id:
#print (item.video_id, ids)
return (item.video_id, ids)
for i in CatalogItem.objects.filter(parent=item):
if i.is_lock:
find_locks(i, ids.append(i.id))
else:
find_locks(i, ids)
How can I get the list results?
I'd use a recursive generator instead of building a list:
def find_locks(item, ids):
if item.video_id:
yield (item.video_id, ids)
for i in CatalogItem.objects.filter(parent=item):
nxt = ids + [i.id] if i.is_lock else ids
for x in find_locks(i, nxt):
yield x
In python 3.3 you can use yield from for the last part.
Try something like the following:
def find_locks(item, ids):
if item.video_id:
return [(item.video_id, ids)]
res = []
for i in CatalogItem.objects.filter(parent=item):
if i.is_lock:
res.extend(find_locks(i, ids + [i.id]))
else:
res.extend(find_locks(i, ids))
return res
In the base case you return list with the only one item included. If it's not the base case, you make a new list, execute recursive call, extend the list with result of recursive call and return this list.
You can simply store each result in a list and return that at the end:
def find_locks(item, ids):
if item.video_id:
return [(item.video_id, ids)]
result = []
for i in CatalogItem.objects.filter(parent=item):
if i.is_lock:
result.extend(find_locks(i, ids + [i.id]))
else:
result.extend(find_locks(i, ids))
return result
Note that you need to return each item in a list as well because other calls to find_locks expect to receive a list as return value.

Why does list.append() return None? [duplicate]

This question already has answers here:
Why do these list operations (methods: clear / extend / reverse / append / sort / remove) return None, rather than the resulting list?
(6 answers)
Closed 2 years ago.
I am trying to calculate a postfix expression using Python, but it did not work. I think this is maybe a Python-related problem.
Any suggestions?
expression = [12, 23, 3, '*', '+', 4, '-', 86, 2, '/', '+']
def add(a,b):
return a + b
def multi(a,b):
return a* b
def sub(a,b):
return a - b
def div(a,b):
return a/ b
def calc(opt,x,y):
calculation = {'+':lambda:add(x,y),
'*':lambda:multi(x,y),
'-':lambda:sub(x,y),
'/':lambda:div(x,y)}
return calculation[opt]()
def eval_postfix(expression):
a_list = []
for one in expression:
if type(one)==int:
a_list.append(one)
else:
y=a_list.pop()
x= a_list.pop()
r = calc(one,x,y)
a_list = a_list.append(r)
return content
print eval_postfix(expression)
Just replace a_list = a_list.append(r) with a_list.append(r).
Most functions, methods that change the items of sequence/mapping does return None: list.sort, list.append, dict.clear ...
Not directly related, but see Why doesn’t list.sort() return the sorted list?.
The method append does not return anything:
>>> l=[]
>>> print l.append(2)
None
You must not write:
l = l.append(2)
But simply:
l.append(2)
In your example, replace:
a_list = a_list.append(r)
to
a_list.append(r)
For return data on append use:
b = []
a = b.__add__(['your_data_here'])
append function mutates the list and it returns None. This is the piece of code which does that http://hg.python.org/cpython/file/aa3a7d5e0478/Objects/listobject.c#l791
listappend(PyListObject *self, PyObject *v)
{
if (app1(self, v) == 0)
Py_RETURN_NONE;
return NULL;
}
So, when you say
a_list = a_list.append(r)
you are actually assigning a_list with None. So, the next time when you refer to a_list, it is not pointing to the list but the None. So, as others have suggested, change
a_list = a_list.append(r)
to
a_list.append(r)
Functions like list.append(),list.sort() don't return anything.
e.g
def list_append(p):
p+=[4]
function list_append doesn't have an return statement.so when you run following statements:
a=[1,2,3]
a=list_append(a)
print a
>>>None
but when you run following statements:
a=[1,2,3]
list_append(a)
print a
>>>[1,2,3,4]
That's it.so,hoping it can help you.
List methods can be divided in two types those who mutate the lists in place and return None (literally) and those who leave lists intact and return some value related to the list.
First category:
append
extend
insert
remove
sort
reverse
Second category:
count
index
The following example explains the differences.
lstb=list('Albert')
lstc=list('Einstein')
lstd=lstb+lstc
lstb.extend(lstc)
# Now lstd and lstb are same
print(lstd)
print(lstb)
lstd.insert(6,'|')
# These list-methods modify the lists in place. But the returned
# value is None if successful except for methods like count, pop.
print(lstd)
lstd.remove('|')
print(lstd)
# The following return the None value
lstf=lstd.insert(6,'|')
# Here lstf is not a list.
# Such assignment is incorrect in practice.
# Instead use lstd itself which is what you want.
print(lstf)
lstb.reverse()
print(lstb)
lstb.sort()
print(lstb)
c=lstb.count('n')
print(c)
i=lstb.index('r')
print(i)
pop method does both. It mutates the list as well as return a value.
popped_up=lstc.pop()
print(popped_up)
print(lstc)
just a thought, instead of those functions (which manipulates the actual data) returning None, they should have returned nothing.
Then atleast the user would have caught the issue as it would have throwed an error stating some assignment error!!
Comment your thoughts!!
Just in case somebody ends here, I encountered this behavior while trying to append on a return call
This works as expected
def fun():
li = list(np.random.randint(0,101,4))
li.append("string")
return li
This returns None
def fun():
li = list(np.random.randint(0,101,4))
return li.append("string")

Using recursion to create a linked list from a list

how would one go about using recursion in order to take a list of random values and make it a linked list? Where each value is a node. As of right now, i've tried implementing the following...
def pyListToMyList(pylst):
lists = mkMyList()
lists.head = pyListToMyListRec(pylst)
return lists
def pyListToMyList(pylst):
if pylst:
return mkEmptyNode()
else:
return mkNode(pylst[0], pyLstToMyListRec(pylst[1:]))
The problem is the the else statement which returns an error saying that the index is out of range.
def pyListToMyList(pylst):
if not pylst:
return mkEmptyNode()
else:
return mkNode(pylst[0], pyLstToMyListRec(pylst[1:]))
EDIT: Though this is O(n^2) because of all the list copying.
I would do
def pyListToMyList(pylst, i=0):
if i > len(pylst):
return mkEmptyNode()
else:
return mkNode(pylst[i], pyLstToMyListRec(pylst, i+1))
or even more efficient and less likely to overflow stack (though this does not use recursion):
def pyListToMyList(pylst):
lst = mkEmptyNode()
for x in reversed(pylist):
lst = mkNode(x, lst)
return lst

Categories