Functional append/extend - python

The methods append and extend in Python are not functional by nature, they modify the callee and return None.
Is there an alternative way to do what these methods do and get a new list as a returned value?
Consider this example:
def myfun(first, *args):
for elem in [first].extend(args):
print elem
Obviously, this won't work.
Is there a way to construct a new list directly with an expression, instead of being forced to write the following?
def myfun(first, *args):
all_args = list(first)
all_args.extend(args)
for elem in all_args:
print elem
Thanks.

>>> def append(lst, elem):
... return lst + [elem]
...
>>> append([1, 2, 3], 4)
[1, 2, 3, 4]
>>> def extend(lst1, lst2):
... return lst1 + lst2
...
>>> extend([1, 2], [3, 4])
[1, 2, 3, 4]
Is that what you wanted?
You may also define your own type, which returns the list itself on these operations, in addition to change:
>>> class MyList(list):
... def append(self, x):
... super(MyList, self).append(x)
... return self
... def extend(self, lst):
... super(MyList, self).extend(lst)
... return self
...
>>> l = MyList([1, 2, 3])
>>> l.append(4)
[1, 2, 3, 4]
>>> l.extend([5, 6, 7])
[1, 2, 3, 4, 5, 6, 7]
>>> l
[1, 2, 3, 4, 5, 6, 7]

You can rewrite that as:
[first] + args

Related

my swap function is not working in python

please guys, this function is meant to swap a group of items in a list, like the first k items with the last k items, but I dont know how to get the function to work
def swap(L, k):
L[len(L)-k:], L[:k] = L[:k], L[len(L)-k:]
yet when I run this with doctest, it fails
swap([1, 2, 3, 4, 5, 6],2)
Fix the indexes, return a list from the method, and print the resulting list:
def swap(L, k):
return L[(-k):] + L[k:(-k)] + L[:k]
lst = swap([1, 2, 3, 4, 5, 6], 2)
print(lst)
# [5, 6, 3, 4, 1, 2]
Note that the original list is not modified - what is returned is a different list with elements swapped.
The function works perfectly, but you have no other references to the list you're passing in, so it gets discarded. Simply save the list to a name before passing it in.
By the way, the len(L) is unnecessary.
def swap(L, k):
"""
>>> lst = [1, 2, 3, 4, 5, 6]
>>> swap(lst, 2)
>>> lst
[5, 6, 3, 4, 1, 2]
"""
L[-k:], L[:k] = L[:k], L[-k:]
def swap(L, k):
J = L[:k]
L[:k] = L[-2:]
L[-2:] = J
P = [1,2,3,4,5,6]
swap(P,2)
# P ==[5, 6, 3, 4, 1, 2]

Python, RHS of assignment is "None" (this isn't expected) [duplicate]

The methods append and extend in Python are not functional by nature, they modify the callee and return None.
Is there an alternative way to do what these methods do and get a new list as a returned value?
Consider this example:
def myfun(first, *args):
for elem in [first].extend(args):
print elem
Obviously, this won't work.
Is there a way to construct a new list directly with an expression, instead of being forced to write the following?
def myfun(first, *args):
all_args = list(first)
all_args.extend(args)
for elem in all_args:
print elem
Thanks.
>>> def append(lst, elem):
... return lst + [elem]
...
>>> append([1, 2, 3], 4)
[1, 2, 3, 4]
>>> def extend(lst1, lst2):
... return lst1 + lst2
...
>>> extend([1, 2], [3, 4])
[1, 2, 3, 4]
Is that what you wanted?
You may also define your own type, which returns the list itself on these operations, in addition to change:
>>> class MyList(list):
... def append(self, x):
... super(MyList, self).append(x)
... return self
... def extend(self, lst):
... super(MyList, self).extend(lst)
... return self
...
>>> l = MyList([1, 2, 3])
>>> l.append(4)
[1, 2, 3, 4]
>>> l.extend([5, 6, 7])
[1, 2, 3, 4, 5, 6, 7]
>>> l
[1, 2, 3, 4, 5, 6, 7]
You can rewrite that as:
[first] + args

What's wrong with my Python code? I'm trying to deep-reverse a list input

def is_list(p):
return isinstance(p, list)
def deep_reverse(list):
o=[]
for i in reversed(list):
if is_list(i)==True:
print i
deep_reverse(i)
o.append(i)
return o
For example:
p = [1, [2, 3, [4, [5, 6]]]]
print deep_reverse(p)
#>>> [[[[6, 5], 4], 3, 2], 1]
Change the line
deep_reverse(i)
to
i = deep_reverse(i)
Incidentally, a shorter way to write this function would be:
def deep_reverse(lst):
if not is_list(lst):
return lst
return map(deep_reverse, reversed(lst))

Use multiple functions at once on a list

Basically, I have a list and I want to perform multiple functions on it at once. For example,
List = [1,2,3,4,5]
List.extend([1,2,3,4,5]).sort().reverse()
I would like the result to be [5,5,4,4,3,3,2,2,1,1].
I haven't used Python in a while, but I know I've done something like this before. Is it something simple I'm missing or what?
It has to all be on one line by the way.
Most Python methods that mutate a container in-place return None
However your example can easily be handled in one line
L = [1,2,3,4,5]
L = sorted(L+[1,2,3,4,5], reverse=True)
Keeping in the spirit of the challenge, it's not hard to chain the operations (because they always return None)
>>> L = [1, 2, 3, 4, 5]
>>> L.extend([1,2,3,4,5]) or L.sort() or L.reverse() or L
[5, 5, 4, 4, 3, 3, 2, 2, 1, 1]
Here's another way
>>> L = [1, 2, 3, 4, 5]
>>> (L.extend([1,2,3,4,5]), L.sort(), L.reverse()) and L
[5, 5, 4, 4, 3, 3, 2, 2, 1, 1]
And you can let your imagination run wild
>>> L = [1, 2, 3, 4, 5]
>>> max(L.extend([1,2,3,4,5]), L.sort(), L.reverse(), L) # Python2.x only
[5, 5, 4, 4, 3, 3, 2, 2, 1, 1]
You cannot chain the above operations since they are performed in-place.
As alternatives, use sorted() and reversed().
How about:
>>> l = [1,2,3,4,5]*2
>>> l.sort(reverse=True)
>>> l
[5, 5, 4, 4, 3, 3, 2, 2, 1, 1]
Or even shorter:
>>> sorted([1,2,3,4,5]*2,reverse=True)
[5, 5, 4, 4, 3, 3, 2, 2, 1, 1]
Each of those functions acts on the list in-place, returning None and not the modified list. You'd have to do something like
l = [1,2,3,4,5]
l = reversed(sorted(l + [1,2,3,4,5]))
Not perfect but interesting..
class chain():
def __init__(self, my_object):
self.o = my_object
def __getattr__(self, attr):
x = getattr(self.o, attr)
if hasattr(x, '__call__'):
method = x
return lambda *args: self if method(*args) is None else method(*args)
else:
prop = x
return prop
list_ = chain([1, 2, 3, 0])
print list_.extend([9,5]).sort().reverse()
The functions extend, sort and reverse doesn't return list but change the list on which they are called. Chaining relies on a fact that previous function returns some value and works on it.
E.g. s="abc" then you can do s.upper().lower() as .upper() return a new string in uppercase (ans same for .lower()).

Access deep list nested values by reference in Python

I have a list with nested lists and I want to create a function (modify_list) that gets a tuple and modifies the passed pointer with a passed value argument. The problem is that I'm not sure how to modify a nested value like this programmatically by reference.
Simplified example:
l = [[1, [2,3, [4,5,6]]]]
If I call the function modify_list, these would be how to use it and the expected results:
> l[0][1][2][2]
6
> modify_list((0, 1, 2, 2), 8)
> l
[[1, [2,3, [4,5,8]]]]
> modify_list((0, 1, 1), 14)
> l
[[1, [2,14, [4,5,8]]]]
Thanks
You can determine each sublist by accessing it with the respective index. Use the last index to assign the value:
def set_nested_val(l, indices, val):
for i in indices[:-1]:
l = l[i]
l[indices[-1]] = val
Note that this function operates on an arbitrary list (the first argument), and not only l. If you want to always modify l, use functools.partial:
import functools
l = [[1, [2,3, [4,5,6]]]]
modify_list = functools.partial(set_nested_val, l)
Note that nested lists, and accessing values by indicies, are often a sign of a bad data architecture. Have you considered a dict whose keys are tuples?
def modify_list(indices, new_value):
x = reduce(lambda x, i: x[i], indices[:-1], l)
x[indices[-1]] = new_value
Example:
>>> l = [[1, [2, 3, [4, 5, 6]]]]
>>> modify_list((0, 1, 2, 2), 8)
>>> l
[[1, [2, 3, [4, 5, 8]]]]
This method matches what you are asking for in your question, but it probably makes more sense to pass in the list that you want to mutate instead of always modifying the global variable:
def modify_list(lst, indices, new_value):
x = reduce(lambda x, i: x[i], indices[:-1], lst)
x[indices[-1]] = new_value
>>> l = [[1, [2, 3, [4, 5, 6]]]]
>>> modify_list(l, (0, 1, 2, 2), 8)
>>> l
[[1, [2, 3, [4, 5, 8]]]]
Try this:
def modify_list(lst, pos, val):
item = lst
while len(pos) > 1:
item = item[pos[0]]
pos = pos[1:]
item[pos[0]] = val
Or this:
def modify_list(lst, pos, val):
item = lst
for i in pos[:-1]:
item = item[i]
item[pos[-1]] = val
Or this:
def modify_list(lst, pos, val):
reduce(lambda a, e: a[e], pos[:-1], lst)[pos[-1]] = val
In any case, use it like this:
lst = [[1, [2, 3, [4, 5, 6]]]]
modify_list(lst, (0, 1, 2, 2), 8)
lst
> [[1, [2, 3, [4, 5, 8]]]]

Categories