Lists

Calvin (Deutschbein)

W8Fri: 18 Oct

Announcements

  • Project 2: Breakout for Monday, 21 October, 11:59 PM.
    • Done with ball / starting collisions
    • gw.get_element_at(x, y)
  • I'll post PS5 tonight but you don't need to worry about it. Only 2 problems.

Today

  • Lists
    • Value vs Reference
    • Copys
    • List methods
    • Comprehensions

Values

  • There is an important fundamental difference between lists and integers
    • And strings, floats, booleans, etc...
  • A number, like '7', is a value.
    • Values are unchanging, like strings and booleans.
    • A variable set to be equal to a value may which value is equal to
    • But changing a variable to a new value does not alter any underlying value, like 7.

Values

  • We can see this using the built-in 'id' function.
    • id gives the address a value lives at within the computer >>> id(7) 140732622441080 >>> id(8) 140732622441112 >>> x = 7 >>> id(x) 140732622441080 >>> x = 8 >>> id(x) 140732622441112
    • 7 always lives at 080
    • 8 always lives at 112
    • If 'x' is equal to 7, it lives at 080, but not if it equals 8.

Values

  • When we set variables equal to a value...
    • If we change the value of one variable, the other variable is unaltered. >>> x = 1 >>> y = x >>> x = 2 >>> print(y) 1 >>> id(x), id(y), id(1), id(2) (140732622440920, 140732622440888, 140732622440888, 140732622440920)
    • Really, these variables are just holding keeping track of where 1 and 2 live.

References

  • "Where something lives" is called a reference.
    • Every time the integer 1 is used in Python, it is always "the same 1"
    • This is not true for lists... >>> x = [1] >>> y = x >>> x = [1] >>> y [1] >>> id(x), id(y) (2199204204928, 2199208697472)
    • There can be more than one distinct "lists that contains 1"

References

  • Sometimes, changing one variable may change another...
    • If we set y equal to x, then they correspond to the same reference, the same list...
    • If we change a value in that list, it changes for both x and y, because they refer to the same list. >>> x = [1] >>> y = x >>> y[0] = 2 >>> x [2]
      • We can make x and y both a list containing 1 (then containing 2), and also the same.

References

  • Sometimes, changing one variable may not change another...
    • We can check to see if the lists are the same list, and not just containing the same values.
    • If we change a value in that list, it changes for both x and y, because they refer to the same list. >>> x = [1] >>> y = [1] >>> x == y True >>> x is y False >>> x = y >>> x is y True
    • If changing two lists that single-equals-comparison, one or both may change.
    • If changing two lists that 'is' operator, both change or neither.

References

  • We can use references to allow functions to change the values from outside of the function.
    • This is how gw.box works, by the way.
    • 'gw' is a reference. >>> x = [0] >>> def embiggen(): ... x[0] = x[0] + 1 ... >>> x [0] >>> embiggen() >>> x [1]
    • If you find this confusing, you are correct (it's confusing).

Copies

  • My advice: Just make a new copy if you aren't sure.
    • y = x sets y to the same reference as x.
    • y = x[:] creates a slice (a new reference) with all the same things as x >>> x = [1,2] >>> y = x >>> id(x), id(y) (2199208697472, 2199208697472) >>> x += [3] >>> x, y ([1, 2, 3], [1, 2, 3])
    • If you find this confusing, you are correct (it's confusing).

Copies

  • My advice: Just make a new copy if you aren't sure.
    • y = x sets y to the same reference as x.
    • y = x[:] creates a slice (a new reference) with all the same things as x >>> y = x[:] >>> x, y ([1, 2, 3], [1, 2, 3]) >>> id(x), id(y) (2199208697472, 2199204204928) >>> x += [4] >>> x, y ([1, 2, 3, 4], [1, 2, 3])
    • If you find this confusing, you are correct (it's confusing).

Today

  • Lists
    • ✓ Value vs Reference
    • ✓ Copys
    • List methods
    • Comprehensions

Common Useful List Methods

    Method Description
    x.copy() Returns a new list whose elements are the same as the original, same as x[:]
    x.append(val) Adds 'val' to the end of the list, same as x += [val]
    x.insert(loc, val) Inserts 'val' at the specificed index 'loc' in `x`, pushing the rest of `x` to have an index/location that is one greater.
    x.remove(val) Removes the first instance of 'val' from `x` (or error)
    x.reverse() Reverses the order of the elements in the list. Like x[::-1], but x[::-1] creates a new list (with a new id/reference)
    x.sort() Sorts the elements of the list. Returns `none`, but alters the order of the elements in `x`

Sort

  • Sorts the elements of the list. Returns `none`, but alters the order of the elements in `x` >>> y = x.sort() >>> y >>> x [1, 2, 3, 4]
  • If you find this confusing, you are correct (it's confusing).

Sorted

  • 'Sorted' and 'Reversed' return a new list... >>> x = [4,2,3,1] >>> y = sorted(x) >>> y [1, 2, 3, 4] >>> x [4, 2, 3, 1]
  • I only use `sorted` and `x[::-1]` - use what works for you.

Today

  • Lists
    • ✓ Value vs Reference
    • ✓ Copys
    • ✓ List methods
    • Comprehensions

Comprehensions

  • By far the best feature in Python is list comprehensions.
    • Emphasis: By far.
  • This was the div6/7 extra credit technique.
  • We take the square brackets of a list: div6 = [...]
  • We place a for loop inside the list: div6 = [... for num in range(40,60)]
  • We write the expression to perform over each loop iteration... div6 = [num % 6 for num in range(40,60)]

Comprehensions

  • By far the best feature in Python is list comprehensions.
  • This one is complete, we can test it... >>> div6 = [num % 6 for num in range(40,60)] >>> div6 [4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5]

Comprehensions

  • By far the best feature in Python is list comprehensions.
  • This one is complete, we can test it... >>> div6 = [num % 6 == 0 for num in range(40,60)] >>> >>> div6 [False, False, True, False, False, False, False, False, True, False, False, False, False, False, True, False, False, False, False, False]

Comprehensions

  • By far the best feature in Python is list comprehensions
  • Would be easier if we could see which number corresponded to which boolean.
  • No problem - create a list of the number and the boolean, one for each number... >>> div6 = [[num,num % 6 == 0] for num in range(40,60)] >>> >>> div6 [[40, False], [41, False], [42, True], [43, False], [44, False], [45, False], [46, False], [47, False], [48, True], [49, False], [50, False], [51, False], [52, False], [53, False], [54, True], [55, False], [56, False], [57, False], [58, False], [59, False]]
  • That is... also impossible to read...

Comprehensions

  • We can print from inside a comprehension >>> [print(num,num % 6 == 0) for num in range(40,45)] 40 False 41 False 42 True 43 False 44 False [None, None, None, None, None]
  • This creates a list of None as well, but that's okay. We can ignore it.

Comprehensions

  • We can include 'if' statements after the 'for', like so...
  • Take a minute to look at this, it's a complex sentence. >>> [print(num) for num in range(40,45) if num % 6 == 0] 42 [None]
  • This creates a list of None as well, but that's okay. We can ignore it.

Comprehensions

  • We wanted 6 or 7, let's look at that. [print(num) for num in range(40,61) if (num % 6 == 0) != (num % 7 == 0)] 48 49 54 56 60 [None, None, None, None, None]
  • This creates a list of None as well - which, by the way, has a useful length.

Comprehensions

  • We wanted 6 or 7, let's look at that. >>> def div_6_or_7(lo, hi): ... return len([print(num) for num in range(lo,hi+1) if (num % 6 == 0) != (num % 7 == 0)]) ... >>> count = div_6_or_7(40,60) 48 49 54 56 60 >>> print(count) 5
  • I constantly practiced until I could write my loops like this.

Today

  • Lists
    • ✓ Value vs Reference
    • ✓ Copys
    • ✓ List methods
    • ✓ Comprehensions

Announcements

  • Project 2: Breakout for Monday, 21 October, 11:59 PM.
    • Done with ball / starting collisions
    • gw.get_element_at(x, y)
  • I'll post PS5 tonight but you don't need to worry about it. Only 2 problems.