Previous Lecture Lecture 4 Next Lecture

Lecture 4, Thu 01/25

Immutable vs. Immutable, Python Testing

# CS 8, 1-25-18

''' Mutable vs Immutable Types

- Lists in Python are MUTABLE (can change them in place)
'''
"""
# Example

L = [10, 20, 30, 40]
print(L)
L[2] = 300
print(L)

T = (10, 20, 30, 40)
print(T)
#T[2] = 300 # ERROR, tuples are IMMUTABLE
T = (10, 20, 300, 40)
print(T)

school = "UCSB"
#school[3] = "D" #ERROR, strings are IMMUTABLE
school = "UCSD"

from collections import namedtuple
Book = namedtuple('Book', 'title author')
b1 = Book("Harry Potter", "Rowling")
print(b1)
#b1.author = "J.K. Rowling" # ERROR, namedtuples are IMMUTABLE

''' seems intuitive to do something like changing an
attribute, but it's illegal because namedtuples are
IMMUTABLE.
'''

# Q: How can we change it?
# 1: Create a new object and reassign to variable
b1 = Book(b1.title, "J.K. Rowling")
print(b1)

# 2: Use a _replace method
b1 = b1._replace(author="Rowling")
# ._replace returns a new namedtuple and we assign back
# to the variable b1
print(b1)

''' Q: Why should we even care?
- It's the behavior of the language!
- Depending on whether or not something is immutable or
mutable, it affects how the data is treated when passing
it into a function.
'''

def add_to_end(s, i):
    ''' Returns a string with i appended to s '''
    s = s + i
    return s

name = "Richert"
print(add_to_end(name, "!"))
print(name)

# When immutable types are changed in a function, a local
# COPY of the data is made and used within the function.
# Once the function returns, the immutable variable
# does not change (See Chapter 3.5)

def add_to_list(L, i):
    ''' Returns a list with value i appended to it '''
    L.append(i)
    return L

someList = [2, 4, 6, 8]
print(someList)
print(add_to_list(someList, 10))
print(someList)

''' When mutable values are passed into a function,
the actual value is modified '''

''' "None" return type '''

# If a function does not return a value, then
# the "data" is "None".

# It's up to the developer to decide if a function should
# or should not return data depending on the intention
# of using the function

# Example
# print() # print function returns None
print(print()) # print(None) -> None

# Function that returns None
def noReturn():
    ''' prints and returns nothing '''
    print("in Function noReturn()")
    # return optional, but None is returned if there isn't a value

print(noReturn())
"""
''' Python Testing '''

# Software testing is essential to ensure behavior works
# as expected.

# Assert statements can be scattered throughout your code
# If an assert statement fails (i.e. not True), then
# your program execution terminates.

"""
print("1st line")
assert 3 == 3 # Test passes, resumes execution.
print("2nd line")

def double(n):
    ''' Returns 2 * n '''
    return 2 * n

assert double(5) == 10
assert double(-2) == -4
assert double("UCSB") == "UCSBUCSB"
"""

'''pytest is a formal testing framework for python'''
def double(n):
    return 2 * n

def test_double_5():
    assert double(5) == 10

def test_double_negative():
    assert double(-2) == -4

def test_double_list():
    assert double([1,2]) == [1,2,1,2]

def test_double_string():
    assert double("UCSB") == "UCSBUCSB"

''' running pytest on functions that start with "test_" and have
an assert statement will "automate" execution of all tests and
show which ones passed and which ones failed.

- Important since this ensures software is working as expected if
many people try to modify the code at the same time
'''

''' import vs. from '''
- Not much of a difference behind-the-scene, but affects naming.

# "import" Example:
import math # gives us access to functionality in the math library

print(math.sqrt(4)) # how to use a math library function.

# "from" Example:
from math import sqrt

print(sqrt(4)) # no need to use "math." when calling sqrt function

'''
- We can "import" our own code in a file using the file name without
the ".py" extension.
- Good for organizing our code in a modular fashion.
	- Can organize all tests within a file and import functionality
	into the file running the tests.
'''