Reverse function reverses wrong list - python

I am really really new to coding and this is my first post but I haven't found anybody else with the same problem yet.
This is a snippet of my code:
nr_list = [3, 4, 9]
nr_list_r = []
nr_list_r = nr_list
nr_list_r.reverse()
print(nr_list)
It returns [9, 4, 3]
I honestly don't know why nr_list is reversed when I only used the reverse function on nr_list_r.
Why is nr_list reversed as well?

In Python, variables refer to values rather than contain them. So when you do
nr_list_r = nr_list
You're not making a new list. You're making a new variable refer to the same list. If you want to make a copy, you can use the slice syntax [:]
nr_list_r = nr_list[:]
But we also already have a way to reverse a list without modifying it, so you may as well just do it using that built-in function.
nr_list_r = list(reversed(nr_list))
We use reversed to reverse the iterable and then list to convert the result (which is an arbitrary iterable) into a concrete list.

Basically with:
nr_list_r = nr_list
You are just atributting another name to the list "nr_list"
So when you reverse "nr_list_r" the "nr_list" is gonna get reversed aswell.
In order to reverse just one of them you should copy the list
nr_list_r = nr_list.copy()
the full code is like this:
nr_list = [3, 4, 9]
nr_list_r = nr_list.copy()
nr_list_r.reverse()
print(nr_list)
print(nr_list_r)

The concept of References is one of the key optimization in many programming languages.
An object starts its life when it is created. This point of time at least one reference is created.
nr_list = [3, 4, 9] # one reference.
As the execution proceeds, more number of references may get created, based on the usage.
nr_list_r = nr_list # one more reference added.
And also the number of references may be reduced.
nr_list_r = [4,6,8] # one reference reduced.
Finally the object is considered alive, if there at least one reference exists.
When there are no more references, the object is no more accessible and the memory is reclaimed.

Related

Removing earlier duplicates from a list and keeping order

I want to define a function that takes a list as an argument and removes all duplicates from the list except the last one.
For example:
remove_duplicates([3,4,4,3,6,3]) should be [4,6,3]. The other post answers do not solve this one.
The function is removing each element if it exists later in the list.
This is my code:
def remove(y):
for x in y:
if y.count(x) > 1:
y.remove(x)
return y
and for this list:
[1,2,1,2,1,2,3] I am getting this output:
[2,1,2,3]. The real output should be [1,2,3].
Where am I going wrong and how do I fix it?
The other post does actually answer the question, but there's an extra step: reverse the input then reverse the output. You could use reversed to do this, with an OrderedDict:
from collections import OrderedDict
def remove_earlier_duplicates(sequence):
d = OrderedDict.fromkeys(reversed(sequence))
return reversed(d)
The output is a reversed iterator object for greater flexibility, but you can easily convert it to a list.
>>> list(remove_earlier_duplicates([3,4,4,3,6,3]))
[4, 6, 3]
>>> list(remove_earlier_duplicates([1,2,1,2,1,2,3]))
[1, 2, 3]
BTW, your remove function doesn't work because you're changing the size of the list as you're iterating over it, meaning certain items get skipped.
I found this way to do after a bit of research. #wjandrea provided me with the fromkeys method idea and helped me out a lot.
def retain_order(arr):
return list(dict.fromkeys(arr[::-1]))[::-1]

How do i 'replace' an array by filling an empty array's elements using pop method from another array?

I'm trying to implement a stack in python and I'm experimenting with the list data structure. If i want to use the pop method to 'fill' an empty array by using the elements from an existing array, what do I do?
# Implementing Stacks in Python through the given list structure
practiceStack = []
practiceStack.append(['HyunSoo', 'Shah'])
practiceStack.append('Jack')
practiceStack.append('Queen')
practiceStack.append(('Aces'))
# printing every element in the list/array
for i in practiceStack:
print(i)
# since stacks are LIFO (last in first out) or FILO (first in last out), the pop method will remove the first thing we did
emptyArrayPop = []
This is what I tried (by using a for loop) and keep getting a use integers not list error
for i in practiceStack:
emptyArrayPop[i].append(practiceStack.pop)
print(emptyArrayPop)
The pop function is a function — not a value. In other words, practiceStack.pop is a pointer to a function (you can mostly ignore this until you've spent more time around code); you likely want this instead:
practiceStack.pop()
You also need to append to the list; when adding something with append, the List will automatically add it at the end; you do not need to provide an index.
Further explanation: The List.append method will take the value that you pass to it and add that to the end of the List. For example:
A = [1, 2, 3]
A.append(4)
A is now [1, 2, 3, 4]. If you try to run the following:
A[2].append(4)
...then you are effectively saying, "append 4 to the end of the value at position-2 in A", (`A[2] is set to 3 in the above example; remember that python lists start counting at 0, or are "0-index".) which is like saying "Append 4 to 3." This makes no sense; it doesn't mean anything to append an integer to another integer.
Instead, you want to append to the LIST itself; you do not need to specify a position.
Don't get this confused with assigning a value to a position in a List; if you were setting a value at an existing position of a list, you can use the = operator:
>>> B = [1, 2, 3]
>>> B[2]
3
>>> B[2] = 4
>>> print(B)
[1, 2, 4]
>>> B.append(8)
>>> print(B)
[1, 2, 4, 8]
So to answer your original question, the line you want is the following:
emptyArrayPop.append(practiceStack.pop())
(note the [i] has been removed)
[edit] Not the only issue, as #selcuk pointed out.
You will also need to fix the way you're accessing data in the practiceStack list, as you cannot edit a list (calling pop modifies the list in-place) when you are iterating over it.
You will need to iterate over the integer index of the list in order to access the elements of practiceStack:
for i in range(len(practiceStack)):
emptyArrayPop.append(practiceStack.pop())

Python regular expression sub

So I am running into something I cant explain and was hoping someone could shed light on... Here is my code:
fd = open(inFile, 'r')
contents = fd1.readlines()
fd.close()
contentsOrig = contents
contents[3] = re.sub(replaceRegex, thingToReplaceWith, contentsOrig[3])
Now when I print out contents and contentsOrig they are exactly the same. I was trying to preserve what I originally read in but from this little code it doesn't seem to be working. Can anyone enlighten me?
I am running Python 2.7.7
Yes, when you assign a list to another variable, it's not a copy of that list, it is a reference. Meaning there is still one copy of that list and now both variables point to it.
contentsOrig = contents
contentsOrig is contents
# Result: True
When you change one of the values or modify the list in any it is changing the same list. So what you need to do is make a copy of the list. This is done by either of these ways:
contentsOrig = contents[:]
or
contentsOrig = list(contents)
The first way is using the list slicing to produce a new list from the beginning to the end. The second takes a list and returns a new copy of the list.
Note that both ways do not make new copies of the items inside the list. So it's the same items, but different containers. But since these are strings, they are not mutable and therefore if modified inside a list, the original string will be untouched in the the original list.
In Python, mutable objects cannot be copied the way you are copying them. If effect, doing x = y only sets x and y to the same address in memory - they reference the same object (in this case a list). If you use the ID function id(x) and id(y) they will actually be the same!
Edit: note that the poster below showed x is y; the is keyword is using the id function in the background.
A simpler example is here:
list_one = [1, 2, 3]
list_two = list_one
list_one.append(4)
print list_one #will show [1, 2, 3, 4], as expected
print list_two #will ALSO show [1, 2, 3, 4]!
In this case, to get around this problem you can use list splicing to make the new list:
new_list = original_list[:]
If you have multiple nested lists (or other mutable objects), then you can use the deepcopy module to make a copy, if you want all the nested lists to be copied as well.

what do the brackets mean around this python line?

I'm trying to figure out this python what the brackets mean around this python statement:
[self.bids.insert_order(bid[2], Decimal(bid[1]), Decimal(bid[0]), initial=True) for bid in json_doc['bids']]
I'm trying to figure out what the brackets are doing in this. Is it modifying a list in place? I don't get it and I can't figure out how to ask google for the right answer. This is the complete function right here:
def get_level3(self, json_doc=None):
if not json_doc:
json_doc = requests.get('http://api.exchange.coinbase.com/products/BTC-USD/book', params={'level': 3}).json()
[self.bids.insert_order(bid[2], Decimal(bid[1]), Decimal(bid[0]), initial=True) for bid in json_doc['bids']]
[self.asks.insert_order(ask[2], Decimal(ask[1]), Decimal(ask[0]), initial=True) for ask in json_doc['asks']]
self.level3_sequence = json_doc['sequence']
What is a list comprehension?
In essence it means: Do something for every item in the list
Here's a simple example:
exampleList = [1, 2, 3, 4, 5]
#for every item in exampleList, replace it with a value one greater
[item + 1 for item in exampleList]
print(exampleList)
#[2, 3, 4, 5, 6]
List comprehensions are useful when you need do something relatively simple for every item in a list
Understanding your code:
[self.bids.insert_order(bid[2], Decimal(bid[1]), Decimal(bid[0]), initial=True) for bid in json_doc['bids']]
The list we are working with is json_doc['bids']. So for every bid in json_doc['bids'] we insert a new bid with self.bids.insert_order() with all the qualities of that bid which are stored as bid[0], bid[1] etc. In summary, this list comprehension calls the function self.bids.insert_order() for every bid in your json list
To begin with, a list comprehension is a way of constructing a list inline. Say you want to make a list of the first five square numbers. One way would be:
square_list = []
for i in range(1,6):
square_list.append(i**2)
# square_list = [1, 4, 9, 16, 25]
Python has some syntactical sugar to ease this process.
square_list = [i**2 for i in range(1,6)]
I think the most important thing to note is that your example is questionable code. It's using a list comprehension to repeatedly apply a function. That line generates a list and immediately throws it away. In the context of the previous example, it might be akin to:
square_list = []
[square_list.append(i**2) for i in range(1,6)]
This, in general, is kind of a silly structure. It would be better to use either of the first two formulations (rather than mix them). In my opinion, the line you're confused about would be better off as an explicit loop.
for bid in json_doc['bids']:
self.bids.insert_order(bid[2], Decimal(bid[1]), Decimal(bid[0]), initial=True)
This way, it is clear that the object self.bids is being altered. Also, you probably wouldn't be asking this question if it was written this way.

Why does not the + operator change a list while .append() does?

I'm working through Udacity and Dave Evans introduced an exercise about list properties
list1 = [1,2,3,4]
list2 = [1,2,3,4]
list1=list1+[6]
print(list1)
list2.append(6)
print(list2)
list1 = [1,2,3,4]
list2 = [1,2,3,4]
def proc(mylist):
mylist = mylist + [6]
def proc2(mylist):
mylist.append(6)
# Can you explain the results given by the four print statements below? Remove
# the hashes # and run the code to check.
print (list1)
proc(list1)
print (list1)
print (list2)
proc2(list2)
print (list2)
The output is
[1, 2, 3, 4, 6]
[1, 2, 3, 4, 6]
[1, 2, 3, 4]
[1, 2, 3, 4]
[1, 2, 3, 4]
[1, 2, 3, 4, 6]
So in a function the adding a 6 to the set doesn't show but it does when not in a function?
So in a function the adding a 6 to the set doesn't show but it does when not in a function?
No, that is not what happens.
What happens is that, when you execute mylist = mylist + [6], you are effectively creating an entirely new list and putting it in the local mylist variable. This mylist variable will vanish after the execution of the function and the newly created list will vanish as well.
OTOH when you execute mylist.append(6) you do not create a new list. You get the list already in the mylist variable and add a new element to this same list. The result is that the list (which is pointed by list2 too) will be altered itself. The mylist variable will vanish again, but in tis case you altered the original list.
Let us see if a more visual explanation can help you :)
What happens when you call proc()
When you write list1 = [1, 2, 3, 4, 5] you are creating a new list object (at the right side of the equals sign) and creating a new variable, list1, which will point to this object.
Then, when you call proc(), you create another new variable, mylist, and since you pass list1 as parameter, mylist will point to the same object:
However, the operation mylist + [6] creates a whole new list object whose contents are the contents of the object pointed by mylist plus the content of the following list object - that is, [6]. Since you attribute this new object to mylist, our scenario changes a bit and mylist does not point to the same object pointed by list1 anymore:
What I have not said is that mylist is a local variable: it will disappear after the end of the proc() function. So, when the proc() execution ended, the mylist is gone:
Since no other variable points to the object generated by mylist + [6], it will disappear, too (since the garbage collector* will collect it):
Note that, in the end, the object pointed by list1 is not changed.
What happens when you call proc2()
Everything changes when you call proc2(). At first, it is the same thing: you create a list...
...and pass it as a parameter to a function, which will generate a local variable:
However, instead of using the + concatenation operator, which generates a new list, you apply the append() method to the existing list. The append() method does not create a new object; instead, it _changes the existing one:
After the end of the function, the local variable will disappear, but the original object pointed by it and by list1 will be already altered:
Since it is still pointed by list1, the original list is not destroyed.
EDIT: if you want to take a look at all this stuff happening before your eyes just go to this radically amazing simulator:
* If you do not know what is garbage collector... well, you will discover soon after understanding your own question.
Variables in python can always be thought of as references. When you call a function with an argument, you are passing in a reference to the actual data.
When you use the assignment operator (=), you're assigning that name to refer to an entirely new object. So, mylist = mylist + [6] creates a new list containing the old contents of mylist, as well as 6, and assigns the variable mylist to refer to the new list. list1 is still pointing to the old list, so nothing changes.
On the other hand, when you use .append, that is actually appending an element to the list that the variable refers to - it is not assigning anything new to the variable. So your second function modifies the list that list2 refers to.
Ordinarily, in the first case in function proc you would only be able to change the global list by assignment if you declared
global mylist
first and did not pass mylist as a parameter. However, in this case you'd get an error message that mylist is global and local:
name 'mylist' is local and global. What happens in proc is that a local list is created when the assignment takes place. Since local variables go away when the function ends, the effect of any changes to the local list doesn't propagate to the rest of the program when it is printed out subsequently.
But in the second function proc2 you are modifying the list by appending rather than assigning to it, so the global keyword is not required and changes to the list show elsewhere.
As well as the comprehensive answers already given, it's also worth being aware that if you want the same looking syntax as:
mylist = mylist + [6]
...but still want the list to be updated "in place", you can do:
mylist += [6]
Which, while it looks like it would do the same thing as the first version, is actually the same as:
mylist.extend([6])
(Note that extend takes the contents of an iterable and adds them one by one, whereas append takes whatever it is given and adds that as a single item. See append vs. extend for a full explanation.)
This, in one form or another, is a very common question. I took a whack at explaining Python parameter passing myself a couple days ago. Basically, one of these creates a new list and the other modifies the existing one. In the latter case, all variables that refer to the list "see" the change because it's still the same object.
In the third line, you did this
list1=list1+[6]
So, when you did the below after the above line,
print (list1)
which printed list1 that you created at the start and proc procedure which adds list1 + [6] which is creating a new list inside the function proc. Where as when you are appending [6], you are not creating a new list rather you are appending a list item to already existing list.
But, keep in mind. In line 7, you again created the list
list1 = [1,2,3,4]
Now you wanted to print the list1 by calling it explicitly, which will print out the list1 that you reinitialized again but not the previous one.

Categories