Modifying a list outside of recursive function in Python - python

There is a multidimensional list with not clear structure:
a=[[['123', '456'], ['789', '1011']], [['1213', '1415']], [['1617', '1819']]]
And there is a recursive function, which operates the list:
def get_The_Group_And_Rewrite_It(workingList):
if isinstance(workingList[0],str):
doSomething(workingList)
else:
for i in workingList:
get_The_Group_And_Rewrite_It(i)
Through time the get_The_Group_And_Rewrite_It() should get a list, for instance, ['123','456'], and as soon as it get it, doSomething function should rewrite it with ['abc'] in entire list.
The same with other lists of format[str,str,...]. In the end I should get something like
a=[[['abc'], ['abc']], [['abc']], [['abc']]]
I see it would be easy in C++, using *links, but how to do that in Python?

For this case, you can use slice assignment:
>>> a = [[['123', '456']]]
>>> x = a[0][0]
>>> x[:] = ['abc']
>>> a
[[['abc']]]
>>> def f(workingList):
... if isinstance(workingList[0],str):
... workingList[:] = ['abc']
... else:
... for i in workingList:
... f(i)
...
>>> a=[[['123', '456'], ['789', '1011']], [['1213', '1415']], [['1617', '1819']]]
>>> f(a)
>>> a
[[['abc'], ['abc']], [['abc']], [['abc']]]

Related

Deleting an default argument inside function in Python

I have tried the following in the console:
>>> def f(l=[]):
... l.append(1)
... print(l)
... del l
...
>>> f()
[1]
>>> f()
[1, 1]
What I don't understand is how the interpreter is still able to find the same list l after the delete instruction.
From the documentation l=[] should be evaluated only once.
The variable is not the object. Each time the function is called, the local variable l is created and (if necessary) set to the default value.
The object [], which is the default value for l, is created when the function is defined, but the variable l is created each time the function runs.
To delete a element for the list,del l[:] should be used.If u use just l the list will remain itself.
def f(l=[]):
l.append(1)
print(l)
del l[:]
print(l)
>>> f()
[1] #element in the list
[] #list after deletion of the element
>>> f()
[1]
[]
>>> f()
[1]
[]

Empty list appending in the same list. Why it is [[...]] instead of [] [duplicate]

I printed out the contents of a list, and i got the following output:
[[...], [...], [...], [...], [...], [...]]
What are these strange dots?
I used python 2.7.3
Probably you accidentally built a list containing a reference to itself (or here, lots of references):
>>> a = ['x']
>>> a
['x']
>>> a[0] = a
>>> a
[[...]]
The three dots are used so that the string representation doesn't drown in recursion. You can verify this by using id and the is operator:
>>> id(a)
165875500
>>> id(a[0])
165875500
>>> a is a[0]
True

How to mutate a list with a function in python?

Here's a pseudocode I've written describing my problem:-
func(s):
#returns a value of s
x = a list of strings
print func(x)
print x #these two should give the SAME output
When I print the value of x in the end, I want it to be the one returned by func(x). Can I do something like this only by editing the function (and without setting x = func(x))
func(s):
s[:] = whatever after mutating
return s
x = a list of strings
print func(x)
print x
You don't actually need to return anything:
def func(s):
s[:] = [1,2,3]
x = [1,2]
print func(x)
print x # -> [1,2,3]
It all depends on what you are actually doing, appending or any direct mutation of the list will be reflected outside the function as you are actually changing the original object/list passed in. If you were doing something that created a new object and you wanted the changes reflected in the list passed in setting s[:] =.. will change the original list.
That's already how it behaves, the function can mutate the list
>>> l = ['a', 'b', 'c'] # your list of strings
>>> def add_something(x): x.append('d')
...
>>> add_something(l)
>>> l
['a', 'b', 'c', 'd']
Note however that you cannot mutate the original list in this manner
def modify(x):
x = ['something']
(The above will assign x but not the original list l)
If you want to place a new list in your list, you'll need something like:
def modify(x):
x[:] = ['something']

pythonic method to find the inner value of a list

I have the task to either return the element of a list if there is only one element in it, or to return the list itself. The method I am using works for most of my use cases but not for strings.
def inner_value(somelist):
'''
Return somelist[0] if it's a one-element list or the whole list otherwise
:param list somelist: list that might contain only one element
:returns: element of somelist or somelist
>>> inner_value([42])
42
>>> inner_value([42,43])
[42, 43]
>>> inner_value([[42]])
42
>>> inner_value([[42,43]])
[42, 43]
>>> inner_value('spam')
'spam'
>>> inner_value(['spam'])
'spam'
>>> inner_value(['spam','eggs','bacon'])
['spam', 'eggs', 'bacon']
.. warning::
This method does not work for dictionaries (KeyError)
or single character strings (infinite recursion)!
'''
try:
if len(somelist) == 1:
return inner_value(somelist[0])
else:
return somelist
except TypeError:
return somelist
Is there a better way of doing it such that
inner_value('spam') == 'spam'?
You could check the variable type using isinstance method:
if isinstance(somelist, list):
if len(somelist) == 1:
return somelist[0]
else:
return somelist
else:
return somelist
If you only check the len, it would cause problems, since len would give the size of string too:
>>> len(['first','second','third'])
3
>>> len('arbitrary')
9

Python list is not the same reference

This is the code:
L=[1,2]
L is L[:]
False
Why is this False?
L[:] (slice notation) means: Make a copy of the entire list, element by element.
So you have two lists that have identical content, but are separate entities. Since is evaluates object identity, it returns False.
L == L[:] returns True.
When in doubt ask for id ;)
>>> li = [1,2,4]
>>> id(li)
18686240
>>> id(li[:])
18644144
>>>
The getslice method of list, which is called when you to L[], returns a list; so, when you call it with the ':' argument, it doesn't behave differently, it returns a new list with the same elements as the original.
>>> id(L)
>>> id(L[:])
>>> L[:] == L
True
>>> L[:] is L
False

Categories