I found this to be a bit strange. Can anyone explain to me: Why, if I have a list like this:
l = [1, 2, 3, 4, 5]
and I do this reassignment:
l[-1:0] = [99,]
then it inserts the 99 to the left of the 5, like so:
[1, 2, 3, 4, 99, 5]
We must assign to an iterable [99,], assigning to just the integer 99 will give an error, which might be a clue as to what's happening here... I guess?
According to the official Docs:
In the table s is an instance of a mutable sequence type, t is any iterable object and x is an arbitrary object that meets any type and value restrictions imposed by s
Note (1): t must have the same length as the slice it is replacing.
So, if you do l[-1] = 99, you are replacing the item in position -1 (that means, one less than the last) to the value 99.
On the other hand, if you do l[-1:0] = [99,], you taking the elements from index -1 to 0 (that means, a slice of length zero in the position -1), and replacing those by the elements of [99,] (that is why it must be an iterable), which effectively is a semantic insert.
When you slice a Python list with [start:end] you end up with another list. The beginning of the new list in your example is the location of the last element in your original list. Just because the value of l[-1:0] in your example is [] it does not mean that this is simply an empty list. Its value is an empty list, but the reference to l[-1:0] is to a sliced list within an existing list.
So in your example
l = [1,2,3,4,5]
# ^ l[-1:0] starts here but the size is 0
When you assign a list to a sliced position of another list, you are effectively performing list concatenation.
This is the equivalent of what you are doing.
l=[1,2,3,4,5]
l[4:0] = [99] # concatenate a new list at the position of the final element in the original list
# A different way to look at it
l[0:4] + [99] + l[4:]
The result again is effectively concatenating the two lists. More specifically, you are inserting the elements of a new list into the original at the position you've indicated. Using a literal integer such as 99 will result in an error because you cannot concatenate an int and a list directly. However, as others have pointed out, a slice assignment can use any iterable, so l[-1,0] = (99,) works by the same principle.
First, you'll need to know how the slicing works fully. You can have 3 values:
[start:end:step]
In your code, l[-1:0], using -1 as the start value will aim at the last value in the list, but it'll also try and find a list of values because of the end value being set. This is why you had to use a list to change the value.
To solve this issue, use l[-1] = 99 to change the last value of the list to 99 (assuming that's the intended result)
Related
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())
I have been working through a tutorial and encountered unfamiliar Python syntax. Looking to identify what it's called and learn how it works.
Mystery Code
The line(s) in question involve a variable name surrounded by square braces before being set:
[pivot] = get_point_by_id(svg_tree, 'pivot')
Relevant Clue to Posted Answers
My initial thought was that it had something to do with being set to a list since the return value from get_point_by_id is a list.
Untouched, the code runs fine. But if I try to recreate the syntax like this:
[variable_name] = [1,2,3]
print(variable_name)
I get the following error:
ValueError: too many values to unpack (expected 1)
I'll take a guess from your posting: in your first example, pivot is a list that happens to be of the same shape as the functional return. In contrast, variable_name in the second value is not a sequence of three scalars.
The list represents a sequence of values; you can assign the sequence to a matching sequence of variables. For instance:
>>> [a, b] = [2, 3]
>>> a
2
>>> b
3
we usually write this without brackets, simply
a, b = [2, 3]
The left-hand-side of the assignment is the target list.
From 7.2. Assignment statements:
Assignment of an object to a target list, optionally enclosed in
parentheses or square brackets, is recursively defined as follows.
If the target list is a single target with no trailing comma,
optionally in parentheses, the object is assigned to that target.
Else: The object must be an iterable with the same number of items as
there are targets in the target list, and the items are assigned, from
left to right, to the corresponding targets.
The following works because the number of items in the target list is the same as the in the object on the right-hand-side of the assignment.
In [17]: [a] = ['foo']
In [18]: a
Out[18]: 'foo'
In your mystery code, get_point_by_id must return an iterable with one item.
Currently, I have a list as such:
aList = [1,2,3,4,5]
and what I'm trying to do is to emulate 'aList[index] = item' function in python. the program prompts the user for input of negative index and the item to replace.
enter negative index: -2
enter item to replace: 7
this would give me:
[1,2,3,7,5]
since, when the index is negative, python starts counting from the back of the list. Here's my code:
aList = [1,2,3,4,5]
index = int(input("Enter index:"))
item = int(input("Enter item:"))
j = -1 #-1 means the counter should begin with -1 not 0
start = len(aList)-1 #i want python to start from the back of the list
while j<start:
if j == index:
aList[j] = item
j-=1
print(lst)
I'm getting an infinite loop because of the j-=1 and I'm wondering if I'm emulating it correctly?
I think first you need to clear you concept about array.
What is Array.?
Arrays a kind of data structure that can store a fixed-size sequential collection of elements of the same type. An array is used to store a collection of data, but it is often more useful to think of an array as a collection of variables of the same type.
Instead of declaring individual variables, such as number0, number1, ..., and number99, you declare one array variable such as numbers and use numbers[0], numbers1, and ..., numbers[99] to represent individual variables. A specific element in an array is accessed by an index.
All arrays consist of contiguous memory locations. The lowest address corresponds to the first element and the highest address to the last element.
Array In Python
To define a list you simply write a comma separated list of items in square brackets:
myList=[1,2,3,4,5,6]
This looks like an array because you can use "slicing" notation to pick out an individual element - indexes start from 0. For example
print myList[2]
will display the third element, i.e. the value 3 in this case. Similarly to change the third element you can assign directly to it:
myList[2]=100
The slicing notation looks like array indexing but it is a lot more flexible. For example
myList[2:5]
is a sublist from the third element to the fifth i.e. from myList[2] to myList[4]. notice that the final element specified i.e. [5] is not included in the slice.
Also notice that you can leave out either of the start and end indexes and they will be assumed to have their maximum possible value. For example
myList[5:]
is the list from List[5] to the end of the list and
myList[:5]
is the list up to and not including myList[5] and
myList[:]
is the entire list.
List slicing is more or less the same as string slicing except that you can modify a slice. For example:
myList[0:2]=[0,1]
has the same effect as
myList[0]=0
myList[1]=1
Finally is it worth knowing that the list you assign to a slice doesn't have to be the same size as the slice - it simply replaces it even if it is a different size.
I am not sure why you need a loop, when you can just access the elements by index:
aList = [1,2,3,4,5]
index = int(input("Enter index:"))
item = int(input("Enter item:"))
aList[index] = item
Of course your loop is infinite...the variable 'j' keeps getting more negative and you're comparing it so 'start', which is the length of the list minus one.
To my knowledge, indexing with -1 will bring you up the last item in a list e.g.
list = 'ABCDEFG'
list[-1]
'G'
But when you are asking for a sequence from the list, -1 gives the second to last term in a list,
list[3:-1]
'DEF'
Why? I would have expected, and would like to get DEFG
It is because the stop (second) argument of slice notation is exclusive, not inclusive. So, [3:-1] is telling Python to get everything from index 3 up to, but not including, index -1.
To get what you want, use [3:]:
>>> list = 'ABCDEFG'
>>> list[3:]
'DEFG'
>>>
>>> list[3:len(list)] # This is equivalent to doing: list[3:]
'DEFG'
>>>
Also, just a note for the future: it is considered a bad practice to use list as a variable name. Doing so overshadows the built-in.
It's for the same reason that list[3:4] doesn't include the character at the 4th index; slicing is not inclusive. In addition, you can slice from a character to the end simply by omitting the second slice parameter, as in list[3:].
I've a list say, sample_list = [1,2,3,4,5,6,7].
Now, when I try to access:
print(sample_list[-2:2])
or,
print(sample_list[-3:-7])
In both cases, I get an empty list.
Should not it print at-least [6,7] or [5,6,7] respectively, following left-to-right convention?
I know, I'm doing something wrong semantic-wise.
(trying to print the list in right-to-left direction?)
I would like to understand the logic behind empty list. What is happening here?
If you want to slice from right to left, you need to provide a negative step: sample_list[-2:2:-1]. This will also reverse the order of the values.
And a slice like [-2:2] isn't meaningless. If you do sample_list[-2:2] on a list of length two, you'd get a copy of the whole thing. In a list of length three, you'll get a slice with only the middle element. It's only for lists of length 4 or larger, you get an empty slice. If they reversed themselves automatically, then some of those cases would be ambiguous.
Edit: Let me try to make a more comprehensive explanation.
Python's slice syntax is implemented by slice objects. That is, L[start:stop:step] is equivalent to L[slice(start, stop, step)]. (Well, this is how it works in Python 3. For backwards compatibility reasons Python 2 also has an older approach, using __getslice__ and __setslice__ methods, but the newer way with slice objects works too.)
When you take a slice or a list or tuple, you always get elements starting with the index start and continuing up until the element just before stop. The step parameter describes the size of the steps taken, with 2 meaning every other value, and -1 meaning steps in reverse.
Another way of thinking of it is that a slice L[start:stop:step] is almost equivalent to the list comprehension [L[i] for i in range(start, stop, step)]. The differences are only in what happens when some of the values are negative or not provided.
The rule for handling negative values is easy (and it's the same as for non-slice indexing). For start and stop, just add the length of the sequence to any negative value. So, for positive x and y, the slice L[-x:-y] is exactly equivalent to L[len(L)-x:len(L)-y]. Negative step values don't get transformed.
Unlike regular indexing, slicing never raises exceptions for indexes out of range. If indexes are invalid, you may get an empty result, or just fewer values than the slice was asking for.
Not all arguments to a slice are required. A slice object's constructor assigns None as default values for any argument not provided. What those Nones mean for start and stop differs depending on the sign of step, and also on the dimensions of the list that's being sliced.
If step is None it is always treated as if it was 1. If step is positive (or None), a start value of None is treated as if it was 0 and a stop value of None is treated like len(L). If step is negative, a start value of None is treated as -1 and stop value of None is treated as -len(L)-1.
So, to circle back to your question, when you do the slice sample_list[-2:2], several things happen:
First off, a slice object is created, as if you did slice(-2, 2). That slice object will have a step of None, since you didn't provide a third value.
Next, the slice is passed to the list and the values are interpreted. Since step was None, the default of 1 is used. Since start is negative, the length of the list is added to it.
Finally, the results are figured out. For your example list with seven values, you get the equivalent of [sample_list[i] for i in range(5, 2, 1)]. Since the range is empty, the slice is too.
Depending on what you wanted, you can fix this in a few different ways. You could leave it be and you'll get results only for very short source lists, where len(L)-2 is less than 2. Alternately, you could swap the order of your first two arguments, and get the result [3,4,5]. Or you could add a negative step and slice from right to left, resulting in [6, 5, 4].
Remember that indexes start at 0:
sample_list = [1,2,3,4,5,6,7]
# 0 1 2 3 4 5 6
When you do sample_list[-2:2], you're trying to get the second last element to the third element.
But you can't just go from negative to positive (unless you add in a negative step). If you wish to obtain a reversed list, then add a step:
>>> print sample_list[2:-2][::-1]
[5, 4, 3]
This is the same problem with your second example. You're trying to go backwards with negative indicies, but you can't... unless... you add in a negative step!:
>>> print sample_list[-3:-7:-1]
[5, 4, 3, 2]