Python short cut to fill list - python

Java has Arrays.fill(A,1). For a pre-existing List A, is there a shortcut for filling the list with 1? I am writing a function that takes an array and changes the array in some ways. Since arrays are pointers, my function will not return an array. The caller will see the changes after my function returns. The first step in my function is to fill the array with 1s. Doing
def my_work(A):
A =[1]*len(A)
# more work on A
does not seem to change A when my_work is done.
So is my only option
for i in range(len(A)):
A[i]=1
or is there a shortcut? Mine looks like a workaround.

If you really want to change A in place, the A[:] syntax should work:
>>> A = [1,2,3]
>>> def my_work(A):
... A[:] = [1]*len(A)
...
>>> A
[1, 2, 3]
>>> my_work(A)
>>> A
[1, 1, 1]
And here is the relevant section of the tutorial ("assignment to slices").

A is not changing because your not returning it our of my_work. Once my_work is complete the A you have in there is not referenced.
def my_work(A):
A =[1]*len(A)
return A #This line is needed
A = my_work(A)
Another way to do this is something like this.
def reset_list(L, x):
return [x for i in xrange(len(L))]
A = reset_list(A,1)

Related

Why can't a list be constructed and modified in the same line?

For example, why is a not equal to b?
a = [1]
a.append(2)
print(a) # [1, 2]
b = [1].append(2)
print(b) # None
The syntax for b doesn't look wrong to me, but it is. I want to write one-liners to define a list (e.g. using a generator expression) and then append elements, but all I get is None.
It's because:
append, extend, sort and more list function are all "in-place".
What does "in-place" mean? it means it modifies the original variable directly, some things you would need:
l = sorted(l)
To modify the list, but append already does that, so:
l.append(3)
Will modify l already, don't need:
l = l.append(3)
If you do:
l = [1].append(2)
Yes it will modify the list of [1], but it would be lost in memory somewhere inaccessible, whereas l will become None as we discovered above.
To make it not "in-place", without using append either do:
l = l + [2]
Or:
l = [*l, 2]
The one-liner for b does these steps:
Defines a list [1]
Appends 2 to the list in-place
Append has no return, so b = None
The same is true for all list methods that alter the list in-place without a return. These are all None:
c = [1].extend([2])
d = [2, 1].sort()
e = [1].insert(1, 2)
...
If you wanted a one-liner that is similar to your define and extend, you could do
c2 = [1, *[2]]
which you could use to combine two generator expressions.
All built-in methods under class 'List' in Python are just modifying the list 'in situ'. They only change the original list and return nothing.
The advantage is, you don't need to pass the object to the original variable every time you modify it. Meanwhile, you can't accumulatively call its methods in one line of code such as what is used in Javascript. Because Javascript always turns its objects into DOM, but Python not.

Initializing a list and appending in one line

How can I initialize a list, if it is not already initialized and append to it in one line. For example,
function example(a=None):
a = a or []
a.append(1)
return another_function(a)
How can I combine those two statements in the function into one?
I am looking for something like this, but that does not work:
function example(a):
a = (a or []).append(1)
return another_function(a)
EDIT: I don't reference a elsewhere, it is just being passed from function to function. Practically just value is important, so it is OK if it is another object with the right value. I also added a default value of None.
def example(a):
return a + [1] if a else [1]
>>> example([1,2,3])
[1, 2, 3, 1]
>>> example([])
[1]

Python - external variable being changed by function

I am trying to write a function that squares each value in a list, returning a new list with individual values squared. I pass a list to it and it changes the original list. I'd like it to not make any changes to the original list, so that I can use it in other functions.
def squareset(c):
d=c
count = len(c)
print(c)
for i in range(0,(count),1):
d[i]=d[i]**2
return d
test = [1,2,3]
print(squareset(test))
print(test)
I don't have this problem with functions operating on simple variables of type int or float.
I added the d=c line trying to prevent the change to the list test, but it makes no difference. print(test) is producing the result [1,4,9] instead of [1,2,3]. Why is this happening and how can I fix this?
Doing d=c simply makes the parameter d point to the same object that c is pointing to. Hence, every change made to d is made to the same object that c points to.
If you want to avoid changing c you'll have to either send a copy of the object, or make a copy of the object inside the function and use this copy.
For example, do:
d = [i for i in c]
or:
d = c[:]
instead of:
d = c
Assigning the list to another variable doesn't copy the list. To copy, just
def squareset(c):
d=c[:]
...
While the other answers provided are correct I would suggest using list comprehension to square your list.
In [4]:
test = [1,2,3]
results = [elm**2 for elm in test]
print test
print results
[1, 2, 3]
[1, 4, 9]
If you wanted a function:
def squareList(lst):
return [elm**2 for elm in lst]
Try this:
def square(var):
return [x*x for x in var]
x = [1,2,3]
z = square(x)

How to initialise a list inside a loop and then append?

It is possible to initialise a list inside a loop, and append objects to the list in the same loop, without always clearing the list when initalising it?
for j in range(5):
mylist=[]
mylist.append(j)
The result would be a list with one element, but of course I want a list with 5 elements. Is there a nice way to do that?
I'm asking because I need to initialise a list in a function and use this function several times, without clearing the list each time I use the function, but appending the new object. You understand what I mean? At the moment I'm using something like this:
if first == True:
mylist = []
first = False
mylist.append("bla")
but it doesn't looks nice.
Thanks in advance and sorry for my english :)
You can define your function to receive a default argument:
def f(element, L = []):
L.append(element)
print L # you can also use 'return L'
# test
for i in range(5):
f(i)
Output:
[0]
[0, 1]
[0, 1, 2]
[0, 1, 2, 3]
[0, 1, 2, 3, 4]
This will work because the default arguments are evaluated only once.
Why don't you just initialize the list before the loop/function?
save_elem_internal_list = []
def save_elem(elem):
save_elem_internal_list.append(elem)
If you want to avoid the global variable, you can store the data in the function itself:
def save_elem(elem):
if not hasattr(elem, 'store'):
elem.store = []
elem.store.append(elem)
Both of these solutions more obvious than the list-default-argument version by Christian, which is a bit too subtle for my taste. In my experience, that just leads to headache later on.

Add an object to a python list

I am trying to add an object to a list but since I'm adding the actual object when I try to reset the list thereafter, all the values in the list are reset.
Is there an actual way how I can add a monitor object to the list and change the values and not affect the ones I've already saved in the list?
Thanks
Code:
arrayList = []
for x in allValues:
result = model(x)
arrayList.append(wM)
wM.reset()
where wM is a monitor class - which is being calculated / worked out in the model method
Is your problem similar to this:
l = [[0]] * 4
l[0][0] += 1
print l # prints "[[1], [1], [1], [1]]"
If so, you simply need to copy the objects when you store them:
import copy
l = [copy.copy(x) for x in [[0]] * 4]
l[0][0] += 1
print l # prints "[[1], [0], [0], [0]]"
The objects in question should implement a __copy__ method to copy objects. See the documentation for copy. You may also be interested in copy.deepcopy, which is there as well.
EDIT: Here's the problem:
arrayList = []
for x in allValues:
result = model(x)
arrayList.append(wM) # appends the wM object to the list
wM.reset() # clears the wM object
You need to append a copy:
import copy
arrayList = []
for x in allValues:
result = model(x)
arrayList.append(copy.copy(wM)) # appends a copy to the list
wM.reset() # clears the wM object
But I'm still confused as to where wM is coming from. Won't you just be copying the same wM object over and over, except clearing it after the first time so all the rest will be empty? Or does model() modify the wM (which sounds like a terrible design flaw to me)? And why are you throwing away result?
You need to create a copy of the list before you modify its contents. A quick shortcut to duplicate a list is this:
mylist[:]
Example:
>>> first = [1,2,3]
>>> second = first[:]
>>> second.append(4)
>>> first
[1, 2, 3]
>>> second
[1, 2, 3, 4]
And to show the default behavior that would modify the orignal list (since a name in Python is just a reference to the underlying object):
>>> first = [1,2,3]
>>> second = first
>>> second.append(4)
>>> first
[1, 2, 3, 4]
>>> second
[1, 2, 3, 4]
Note that this only works for lists. If you need to duplicate the contents of a dictionary, you must use copy.deepcopy() as suggested by others.
while you should show how your code looks like that gives the problem, i think this scenario is very common. See copy/deepcopy
If i am correct in believing that you are adding a variable to the array but when you change that variable outside of the array, it also changes inside the array but you don't want it to then it is a really simple solution.
When you are saving the variable to the array you should turn it into a string by simply putting str(variablename). For example:
array.append(str(variablename))
Using this method your code should look like this:
arrayList = []
for x in allValues:
result = model(x)
arrayList.append(str(wM)) #this is the only line that is changed.
wM.reset()

Categories