Materials+ML Workshop Day 2¶

logo

Day 2 Agenda:¶

  • Questions about Day 1 Material
  • Review of Day 1

Content for today:

  • Functions:
    • Functions and Data types
    • Writing Python Functions
    • Documenting Functions
    • Default parameters
  • Python classes:
    • Writing Python Classes
    • Instance variables
    • Methods

The Workshop Online Book:¶

https://cburdine.github.io/materials-ml-workshop/¶

Tentative Workshop Schedule:¶

Session Date Content
Day 0 06/16/2023 (2:30-3:30 PM) Introduction, Setting up your Python Notebook
Day 1 06/19/2023 (2:30-3:30 PM) Python Data Types
Day 2 06/20/2023 (2:30-3:30 PM) Python Functions and Classes
Day 3 06/21/2023 (2:30-3:30 PM) Scientific Computing with Numpy and Scipy
Day 4 06/22/2023 (2:30-3:30 PM) Data Manipulation and Visualization
Day 5 06/23/2023 (2:30-3:30 PM) Materials Science Packages
Day 6 06/26/2023 (2:30-3:30 PM) Introduction to ML, Supervised Learning
Day 7 06/27/2023 (2:30-3:30 PM) Regression Models
Day 8 06/28/2023 (2:30-3:30 PM) Unsupervised Learning
Day 9 06/29/2023 (2:30-3:30 PM) Neural Networks
Day 10 06/30/2023 (2:30-3:30 PM) Advanced Applications in Materials Science

Questions¶

Material covered yesterday:

  • Boolean variables
  • Conditional statements and comparison operators
  • Loops (for and while)
  • Lists and Tuples
  • Sets and Dictionaries

Review: Lists and Tuples¶

Lists and tuples store sequences of values:

In [ ]:
my_list = [ 1, 2, 3, 4 ]
my_tuple = ( 1, 2, 3, 4 )

What are the differences between lists and tuples?

  • Lists are mutable (they can be modified)
  • Tuples are immutable (they cannot be modified)

Example: List modification¶

In [2]:
print(my_list)

# modify list:
my_list[-1] = 100
my_list[0] = 100
my_list.append(-4)

# printn modified list
print(my_list)
[1, 2, 3, 4]
[100, 2, 3, 100, -4]

Review: Sets and Dictionaries¶

  • Sets store an unordered collection of unique values
  • Dictionaries associate values with a set of unique keys
In [3]:
my_set = { 'A', 'B', 'C', 'D', 'C'}
my_dict = { 'A' : 1, 'B' : 11, 'C' : 12, 'D' : 0}

print(my_set)
print(my_dict)
{'B', 'C', 'D', 'A'}
{'A': 1, 'B': 11, 'C': 12, 'D': 0}
  • Lists cannot be keys in a dictionary or values in a set because they are immutable
In [4]:
illegal_set = { [1,2,3], [1,2], [1,5] }
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
/tmp/ipykernel_28924/296782444.py in <module>
----> 1 illegal_set = { [1,2,3], [1,2], [1,5] }

TypeError: unhashable type: 'list'
In [5]:
# immutable types can be values in sets and keys in dictionaries:
tuple_set = { (1,1), (1,2), (1,3) }
tuple_dict = { (1,2): 'A', (2,3): 'B' }

New Content:¶

  • Python functions
  • Python classes

Python Functions:¶

  • In Mathematics, Functions are transformations that map inputs to outputs
    • In Python, functions are blocks of code that compute these transformations
    • Functions can have inputs, outputs, or even modify variables
  • We have already encountered few functions in Python, such as print()
  • We have also seen functions associated with lists and tuples:
In [6]:
# len() returns the length of a tuple, list, set, str, or dict:
my_list = [ 1, 2, 3, 4 ]
print( len(my_list) )
4
In [7]:
# list.append() adds a value to the end of a list
my_list.append(10)
print(my_list)
[1, 2, 3, 4, 10]

More examples of functions:¶

In [8]:
# set.add() adds a value to a set:
my_set = {1,2,3}
my_set.add(2)
my_set.add(5)

print(my_set)
{1, 2, 3, 5}
In [9]:
my_dict = { 'A' : 0, 'B' : 2, 'C' : 1 }

# dict.values() returns the values in a dictionary:
dict_vals = list( my_dict.values() )
print(dict_vals)
[0, 2, 1]

Writing Python Functions¶

Functions in Python can be defined using a def statement:

In [10]:
# create a function to print out a greeting:
def greet():
    print('Hello there!')
  • The name of the function (greet) follows def
  • After the function name is list parameters in parentheses (there none in this case)
  • The function is followed by an indented block of code (the function body)
  • A function can optionally output a value using the return statement.

Function parameters and returned values:¶

In [11]:
# create a function to add two numbers:
def add_numbers(a,b):
    total = a + b
    return total # <-- output of function

# store the returned value of a + b in `result`:
result = add_numbers(3,5)

print(result)
8
  • The parameters (a and b) are "temporary variables that store the values that are passed to function.
  • Returned values can be assigned to a variable when the function is called

Exercise: Quadratic Solver¶

Let’s write a Python function that solves for the roots of a quadratic equation of the form

$$f(x) = ax^2 + bx + c$$

where the coefficients $a,b,c$ are passed as parameters to the function.

Documenting Functions¶

  • It is important to write comments that describe what a function does.
  • We do this with special comments called docstrings ("""...""")
In [12]:
# Short docstring for a function:
def greet(name):
    """ prints a greeting for the given name """
    print('Hello, ' + name + '!')
  • Function docstrings get printed when the help function is called:
In [13]:
help(greet)
Help on function greet in module __main__:

greet(name)
    prints a greeting for the given name

Default Arguments¶

  • Default arguments let us supply default values for parameters:
In [14]:
def greet(name, message="Hello"):
    """ Prints a greeting with a name and a message """
    print(message + ', ' + name + '!')

# call greet with the default message:
greet('Albert')

# call greet with a non-default message:
greet('Albert', 'Greetings')
Hello, Albert!
Greetings, Albert!

Objects in Python¶

  • In computer programming, an object is something that contains data and has prescribed behaviors.
  • In Python, every data type that we have encountered so far (list, str, set, etc.) is an object.
  • The data and behaviors of an object are described in something called a class
  • Classes are an important concept in Object-Oriented Programming (OOP)
In [15]:
print(type('Hello World'))
print(type([1,2,3,4]))
print(type({'A','B','C'}))
<class 'str'>
<class 'list'>
<class 'set'>

Python Classes¶

  • Classes serve as a kind of blueprint for objects.
  • We can define our own classes in Python as follows:
  • Classes typically represent real-world objects, concepts, or services.
  • Using classes to abstract away concepts, data, and behaviors can simplify the complexity of large codebases
  • Many Python packages employ classes to abstract away the details of computations, functionality provided, etc.

Example: Writing a Dog class:¶

In [16]:
class Dog:
    """ This class represents a pet dog """
       
    def __init__(self, dog_name):
        """ Constructs a Dog instance with given name """
        self.name = dog_name
  • Inside the class body, we can define the behaviors of objects by writing functions
  • Functions defined in a class are sometimes called methods
  • All methods should begin with self as the first parameter
  • Python classes have a special constructor method, which always has the name __init__.
    • The constructor is a function used for creating instances of a class
    • Inside the constructor, we can create variables associated with an instance (self.name)
    • Variables associated with an object instance are called instance variables.

Constructing Objects¶

In [17]:
class Dog:
    """ This class represents a pet dog """
       
    def __init__(self, dog_name):
        """ Constructs a Dog instance with given name """
        self.name = dog_name
In [18]:
# construct two different Dog objects:
my_dog = Dog('Snoopy')
my_other_dog = Dog('Fido')
In [19]:
# print the names of the dogs:
print(my_dog.name, my_other_dog.name)

# assign the name of one dog to:
my_other_dog.name = 'Rover'

print(my_dog.name, my_other_dog.name)
Snoopy Fido
Snoopy Rover
In [20]:
class Dog:
    """ This class represents a pet dog """

    def __init__(self, dog_name, dog_age=1):
        """ Constructs a Dog instance with given name """
        self.name = dog_name
        self.age = dog_age
        self.tricks = []

    def human_years_age(self):
        """ returns age in human-scale years (7x age) """
        return 7 * self.age

    def add_trick(self, trick):
        """ Adds a trick to this dog's routine of tricks """
        self.tricks.append(trick)

    def do_tricks(self):
        """ Performs this dog's routine of tricks """
        for trick in self.tricks:
            print(self.name, ':', trick)
In [21]:
# create a dog named Buddy:
my_dog = Dog('Buddy', 2)

# print dog name and age:
print('Name:', my_dog.name)
print('Age:', my_dog.age)

# print age in human years:
print('Age in human-scale years:', my_dog.human_years_age())

# add some tricks:
my_dog.add_trick('Sit')
my_dog.add_trick('Shake')
my_dog.add_trick('Roll Over')

# perform all added tricks:
my_dog.do_tricks()
Name: Buddy
Age: 2
Age in human-scale years: 14
Buddy : Sit
Buddy : Shake
Buddy : Roll Over

Recommended Reading:¶

  • Scientific Computing with Numpy and Scipy

If possible, try to do the exercises. Bring your questions to our next meeting on Monday.