Forums

Need help this is CRAZZY ... kinda ;-)

Ok so I would be asking in my class forum but the systems down and this is killing me (No its not the answer to a question). I was doing an assignment when I came across a weird behavior in python 3 for some reason it brutally ripped apart one of my string that I had in a list. It yanked that thing into individual characters including the ' ' white spaces. All the sudden I was like neo in the matrix "whow" I use Spyder (IDE) so I can go through it step by step. HOWEVER when I run this line >>> x[len(x):-1] = p[q] python turns into an axe murderer and goes all crazy on it I can see that python sees the string as a str like it should but for some reason instead of getting output that looks like this

['see spot run', 'y', 3, 4, 5, 6, 1, 'q', 't', 2, 100]

i am getting

['s', 'e', 'e', ' ', 's', 'p', 'o', 't', ' ', 'r', 'u', 'n', 'y', 3, 4, 5, 6, 1, 'q', 2, 100]

WHY????? ITS DRIVING ME CRAZY I MUST KNOW!!!!

p.s. here is my code:

x=[]

w=['t',2,'y',3,100]

y=['see spot run','y',3]

z=[4,5,6,1,'q']

p=x+y+z+w

q=0 n=[0]

for item in p:

if p[q] in x:

    q=q+1

    continue

else:

try:
    x[len(x):-1] = p[q]   ##<--- This is the line thats going crazy
except TypeError:
    n[0] = p[q]
    x=x+n
q=q+1

print(x)

the x[len(x):-1] = p[q] automatically creates a iterator for p[q] and assigns it to x[:] (value unpacking) what you probably want is x.append(p[q]),

I don't know if your simply trying to create a algorithm for getting unique values in a list to practice, but your code could be written as: x=list(set(p))

When you get to processing "see spot run", you're taking a string (which is a Python iterable) and assigning it to a slice of a list (which is also an iterable), so Python walks through the string and adds each element (character) the slice of the list. Here's an experiment (without the weirdly obfuscated code):

x = [0]
x[-1:-1] = "see spot run"
print(x)  ## prints ['s', 'e', 'e', ' ', 's', 'p', 'o', 't', ' ', 'r', 'u', 'n', 0]

x = 0
x[0] = "see spot run" 
print(x)  ## prints ['see spot run']

The primary difference between the two cases above, is that the keft-hand side of the assignment in the first one is an iterable and so the assignment is treated as having an iterable on the right. In the second one, the assignment is simply saying put the string into the zeroth element of the list.

Thank you both lint78 and glenn. I am looking more for a direction to look for the "why" Python3 is unpacking the string. I have already solved the problem"x[len(x):-1] = p[q:q+1]". I just want to know WHY. I think I get what ya'll are saying that its creating an iterator for the p[q]. I assumed that Python would treat "p[q]" as "p[0]" OR "p[1]" OR ..... what ever the value of "q" is(like in my IF statement) like if p = ['a',3,'see spot run'] then p[0] is the object 'a' and p[2] is the str object 'see spot run' as apposed to p[2] being a str that needs to be walked through each element and exploded like Agent Smith . As I had said I solved it already buy changing "p[q]" to p[q:q+1] HOWEVER I am trying to find some "man page" or documentation on a more detailed level about what Python is doing and WHY p[q] (when q = 0) is not being done the same as p[0]. For example:

p = ['see spot run','a',0]

x=[]

x[0] = p[0]

Traceback (most recent call last):

File "<stdin>", line 1, in <module>

IndexError: list assignment index out of range

x= [0]

x[0] = p[0]

x

['see spot run']

x = [0]

x[0:-1] = p[0] <-- This goes crazy and rips it up like a baby with no candy

x

['s', 'e', 'e', ' ', 's', 'p', 'o', 't', ' ', 'r', 'u', 'n', 0]

x[0:-1] = p[0:0+1] <-- BUT this is ok? i guess the baby has its candy?

x

['see spot run', 0]

NOTE: the p[q:q+1] doesn't skip anything it gets them all.

So my question is Can some one point me to some tex/doc/man or something that can clear this up for me I mean why dose x[len(x):-1] = p[q] iterate by element BUT x[len(x):-1] = p[q:q+1] doesn't???

OK, this is definitely a slightly tortured example, but let's recap:

>>> p = ['see spot run','a',1]   
# i've changed the final entry to a 1 to avoid confusion with the 0 that's already in x
>>> x = [0]
>>> x[0:-1] = p[0] 
>>> x
['s', 'e', 'e', ' ', 's', 'p', 'o', 't', ' ', 'r', 'u', 'n', 0]
# that's all the characters in the string, plus the zero that was originally in x

>>> x[0:-1] = p[0:1]
>>> x
['see spot run', 0]
# now that's the whole string as one element, plus the original zero

What's going on? Well, the left-hand side is the same in each case, it's saying:

"take my list x, and replace everything from the first position to the second-last position with whatever's on the right"

So, what's on the right?

>>> p[0]
'see spot run'
>>> len(p[0])
12
# an iterable string, made up of 12 characters

>>> p[0:1]
['see spot run']
>>> len(p[0:1])
1
# an iterable list, with one element in it

So Python is actually doing the same thing in each case. It's replacing the beginning of list x with the items from the iterable on the right, leaving the "0" that's at position -1 in place each time. You could have any other iterable on the right if you wanted:

>>> x[0:-1] = range(10)
>>> x 
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0]

Does that make sense? I have to say it took me a while to get comfortable with it....

As Harry said I think what is confusing you is the right hand side evaluation in your last two examples. The fact is that p[0] and p[0:1] actually return different things, in the first case it returns a string (that can be an iteratable used in slice assignment), while the second case in python slice extraction always returns a new list independently of the slice size (that again is itself a iteratable). This has to do with the implementation of the 'getitem' and 'setitem' methods (they are actually wrapper methods, but that doesn't matter) in the list class which distinguish if the index is an int or a slice object and return different things accordingly.

1st again Thank you lint78 and Harry. I think i get what your saying, the (correct me if I am wrong) right hand sides respectfully are each doing something different. Like p[0] is "pointing" to the object located in memory block xblabla1. While p[0:1] is saying "This IS the object and its in memory block xblabla1". I.E. p[0] is more like a pointer in c++??? AND p[0:1] is more like the actual object??? Either way I think I got a good direction to start off in, so again, again THANK YOU!

Hi @cw,

They are slightly different, but I don't think pointers is quite the right analogy.

p[0] designates a specific object that already exists, the first item in list p, which is a string,

whereas

p[0:1] creates a new object, a list, which is made up of the 0th item from list p.

Hi have to agree with Harry in the sense that python does not have pointers only references. Maybe a good help for you to understand what is happening is to look use http://www.pythontutor.com/visualize.html with your initial code and execute it step by step. Using pythontutor we will be able to see how different stuff is created and referenced. One thing that you will also note is that the reason you need to add a try/except in your initial code is because you can only assign iterables to slices.

Ya I see like in Python, "when you assign one variable to another variable, Python doesn't actually copy the original variable to its target; instead, it "remembers" where the original variable was and uses that original variable when you refer to the copy."(from a lecture-kinda) I just need the principal for now so i can put in some over time on it since it had nothing to do with my class and I believe it to be beyond the scope of my class anyway. Either way Thanks guys.

lint78, http://www.pythontutor.com/visualize.html, That's cool I like the pics. Have you ever used Spyder? It's an IDE that gives the same effect. Not as colorful but it dose allow me to step through the program. That's how I knew what line was giving me the issue.