0% found this document useful (0 votes)
42 views45 pages

Lists Are Objects: Topics: References Alias More On Slicing

Lists are objects that can be compared using ==. Comparing lists checks if they have the same length and identical element values. Lists can be aliased if assigned to multiple variables, meaning changes made through one variable are reflected in the other. Functions that modify lists in-place like sort() return None. When passing lists to functions, the function operates on a reference to the original list rather than a copy, so changes made in the function affect the original list.

Uploaded by

hgtun
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
42 views45 pages

Lists Are Objects: Topics: References Alias More On Slicing

Lists are objects that can be compared using ==. Comparing lists checks if they have the same length and identical element values. Lists can be aliased if assigned to multiple variables, meaning changes made through one variable are reflected in the other. Functions that modify lists in-place like sort() return None. When passing lists to functions, the function operates on a reference to the original list rather than a copy, so changes made in the function affect the original list.

Uploaded by

hgtun
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 45

15.

Lists are Objects

Topics:
References
Alias
More on Slicing
Comparing Lists
You can use == to compare two lists

>>> x = [10,20,30,40]
>>> y = [10,20,30,40]
>>> x==y
True
Comparing Lists
You can use == to compare two lists

x --> 0 ---> 10 y --> 0 ---> 10


1 ---> 20 1 ---> 20
2 ---> 30 2 ---> 30
3 ---> 40 3 ---> 40

The Boolean expression x==y is True because x and y


have the same length and identical values in each element
Comparing Lists
You can use == to compare two lists

>>> x = [1,2,3]
>>> y = [1.0,2.0,3.0]
>>> x==y
True

If there are ints and floats, convert everything to float then compare
Comparing Lists
Do not use <, <= , > , >= to compare two lists

>>> x = [10,20,30,40]
>>> y = [11,21,31,41]
>>> x<y
True
>>> y<x
True

Unpredictable
Aliasing
This:
x = [10,20,30,40]
y = x

Results in this:

0 ---> 10
x --> 1 ---> 20
2 ---> 30
y --> 3 ---> 40
Aliasing
0 ---> 10
x --> 1 ---> 20
y --> 2 ---> 30
3 ---> 40

Things to say:

x and y are variables that refer to the same list


object.

The object is aliased because it has more than one


name.
Tracking Changes

0 ---> 10
x = [10,20,30,40] x --> 1 ---> 20
y = x
2 ---> 30
y = [1,2,3]
3 ---> 40
Tracking Changes

0 ---> 10
x = [10,20,30,40] x --> 1 ---> 20
y = x
y = [1,2,3] y --> 2 ---> 30
3 ---> 40
Tracking Changes

0 ---> 10
x = [10,20,30,40] x --> 1 ---> 20
y = x
2 ---> 30
y = [1,2,3]
3 ---> 40

0 ---> 1
y --> 1 ---> 2
2 ---> 3
The is Operator
>>> x = [10,20,30,40]
>>> y = [10,20,30,40]
>>> x is y
False
0 ---> 10 0 ---> 10
x --> 1 y --> 1 ---> 20
---> 20
2 ---> 30 2 ---> 30
3 ---> 40 3 ---> 40

Even though the two lists have the same component


values. x and y do not refer to the same object.
The is Operator
>>> x = [10,20,30,40]
>>> y = x
>>> x is y
True
0 ---> 10
x --> 1 ---> 20
y --> 2 ---> 30
3 ---> 40

x and y refer to the same object


Making a Copy of a List

0 ---> 10
x = [10,20,30,40] x --> 1 ---> 20
y = list(x)
2 ---> 30
3 ---> 40
Making a Copy of a List

0 ---> 10
x = [10,20,30,40] x --> 1 ---> 20
y = list(x)
2 ---> 30
3 ---> 40

0 ---> 10
y --> 1 ---> 20
2 ---> 30
3 ---> 40
Slices Create new Objects

0 ---> 10
x = [10,20,30,40] x --> 1 ---> 20
y = x[1:]
2 ---> 30
3 ---> 40
Slices Create New Objects

0 ---> 10
x = [10,20,30,40] x --> 1 ---> 20
y = x[1:]
2 ---> 30
3 ---> 40

0 ---> 20
y --> 1 ---> 30
2 ---> 40
Careful!

0 ---> 10
x = [10,20,30,40] x --> 1 ---> 20
y = x
2 ---> 30
y = x[1:]
3 ---> 40
Careful!

0 ---> 10
x = [10,20,30,40] x --> 1 ---> 20
y = x
y = x[1:] y --> 2 ---> 30
3 ---> 40
Careful!

0 ---> 10
x = [10,20,30,40] x --> 1 ---> 20
y = x
2 ---> 30
y = x[1:]
3 ---> 40

0 ---> 20
y --> 1 ---> 30
2 ---> 40
Void Functions

0 ---> 40
x = [40,20,10,30] x --> 1 ---> 20
y = x.sort()
2 ---> 10
3 ---> 30

y -->
Void Functions

0 ---> 10
x = [40,20,10,30] x --> 1 ---> 20
y = x.sort()
2 ---> 30
3 ---> 40

y --> None

Void Functions return None, a special type


Void Functions

0 ---> 40
x = [40,20,10,30] x --> 1 ---> 20
y = list(x)
2 ---> 10
y.sort()
3 ---> 30

0 ---> 40
y --> 1 ---> 20
2 ---> 10
3 ---> 30

Void Functions return None, a special type


Void Functions

0 ---> 40
x = [40,20,10,30] x --> 1 ---> 20
y = list(x)
2 ---> 10
y.sort()
3 ---> 30

0 ---> 10
y --> 1 ---> 20
2 ---> 30
3 ---> 40

Void Functions return None, a special type


Understanding Function Calls
def f(x):
x = x[1:]
print x

if __name__ == '__main__':
u = [1,2,3,4]
f(u)
print u

Looks like f deletes the 0-th character in x


Understanding Function Calls
def f(x): 0 ---> 1
u --> 1 ---> 2
x = x[1:]
print x 2 ---> 3
3 ---> 4
if __name__ blabla
u = [1,2,3,4]
f(u)
print u

Follow the red dot and


watch for impact…
Understanding Function Calls
def f(x): 0 ---> 1
u --> 1 ---> 2
x = x[1:]
print x 2 ---> 3
3 ---> 4
if __name__ blabla
u = [1,2,3,4]
x
f(u)
print u

Parameter x initially refers


to the same object as u
Understanding Function Calls
def f(x): 0 ---> 1
u --> 1 ---> 2
x = x[1:]
print x 2 ---> 3
3 ---> 4
if __name__ blabla
u = [1,2,3,4]
f(u) 0 ---> 2
print u x --> 1 ---> 3
2 ---> 4
x[1:] creates a new object
and x will refer to it
Understanding Function Calls
def f(x): 0 ---> 1
u --> 1 ---> 2
x = x[1:]
print x 2 ---> 3
3 ---> 4
if __name__ blabla
u = [1,2,3,4]
f(u) 0 ---> 2
print u x --> 1 ---> 3
2 ---> 4
2 3 4 is printed
Understanding Function Calls
def f(x): 0 ---> 1
u --> 1 ---> 2
x = x[1:]
print x 2 ---> 3
3 ---> 4
if __name__ blabla
u = [1,2,3,4]
f(u) 0 ---> 2
print u x --> 1 ---> 3
2 ---> 4
1 2 3 4 is printed
Example: The Perfect Shuffle
Permuting the items in a list comes up a lot.

Here is a famous example called the


perfect shuffle:

Before: 10 20 30 40 50 60 70 80

After: 10 50 20 60 30 70 40 80
Executing the Perfect Shuffle
The given list:

10 20 30 40 50 60 70 80

Cut it in half:

10 20 30 40 50 60 70 80

The Re-assemble Process:


Alternately
choose
from the
“half” lists.
Executing the Perfect Shuffle
The given list:

10 20 30 40 50 60 70 80

Cut it in half:

10 20 30 40 50 60 70 80

The Re-assemble Process:


Alternately
choose
10 from the
“half” lists.
Executing the Perfect Shuffle
The given list:

10 20 30 40 50 60 70 80

Cut it in half:

10 20 30 40 50 60 70 80

The Re-assemble Process:


Alternately
choose
10 50 from the
“half” lists.
Executing the Perfect Shuffle
The given list:

10 20 30 40 50 60 70 80

Cut it in half:

10 20 30 40 50 60 70 80

The Re-assemble Process:


Alternately
choose
10 50 20 from the
“half” lists.
Executing the Perfect Shuffle
The given list:

10 20 30 40 50 60 70 80

Cut it in half:

10 20 30 40 50 60 70 80

The Re-assemble Process:


Alternately
choose
10 50 20 60 from the
“half” lists.
Executing the Perfect Shuffle
The given list:

10 20 30 40 50 60 70 80

Cut it in half:

10 20 30 40 50 60 70 80

The Re-assemble Process:


Alternately
choose
10 50 20 60 30 from the
“half” lists.
Executing the Perfect Shuffle
The given list:

10 20 30 40 50 60 70 80

Cut it in half:

10 20 30 40 50 60 70 80

The Re-assemble Process:


Alternately
choose
10 50 20 60 30 70 from the
“half” lists.
Executing the Perfect Shuffle
The given list:

10 20 30 40 50 60 70 80

Cut it in half:

10 20 30 40 50 60 70 80

The Re-assemble Process:


Alternately
choose
10 50 20 60 30 70 40 from the
“half” lists.
Executing the Perfect Shuffle
The given list:

10 20 30 40 50 60 70 80

Cut it in half:

10 20 30 40 50 60 70 80

The Re-assemble Process:


Alternately
choose
10 50 20 60 30 70 40 80 from the
“half” lists.
Implementation 1
def PF1(x):
n = len(x)
m = n/2
Make a copy
top = list(x[:m]) of the top and
bot = list(x[m:]) bottom halves
for k in range(m):
x[2*k] = top[k] They become the
even-indexed and
x[2*k+1] = bot[k] odd-indexed entries

This is a Void function. It returns None.


However, it permutes the values in the list referenced
by x according to the perfect shuffle.
Implementation 2
def PF2(x):
n = len(x) Build y up through
repeated appending
m = n/2
y = []
for k in range(m):
x[k] comes from the
y.append(x[k]) top half of the list,
x[k+m] comes from
y.append(x[k+m]) the bottom half.
return y

This is a fruitful function. It returns a reference


to a list that is the perfect shuffle of the list
referenced by x
Perfect Shuffle Cycles

Question:

Given a length-n list x where n is even, how many


perfect shuffle updates are required before we
cycle back to the original x?
Perfect Shuffle Cycles
Solution Using the Void function PF1:

# Assume x0 is a given list


x = list(x0)
PF1(x)
numPFs = 1
while x!=x0:
PF1(x)
numPFs+=1
print numPFs
Perfect Shuffle Cycles
Solution Using the Fruitful function PF2:

# Assume x0 is a given list


x = PF2(x0)
numPFs = 1
while x!=x0:
x = PF2(x)
numPFs+=1
print numPFs
Sample Outputs

n numPFs
--------------------
8 3
52 8
444 442
1000 36
10000 300
100000 540

You might also like