Skip to content

Writing Functions in Python

Take Notes

Add notes about the concepts you've learned and code cells with code you want to keep.

DOCSTRINGS = is a string written as the first line of a function

DOCSTRING FORMATS = google style, numpydoc, reStructuredText, EpyText

docstring = inspect.getdoc(function)

def the_answer():
    """Retrun the answer to life,
    the universe, and everything.
    
    Retruns:
        int
    """
    
    return 42
print(the_answer.__doc__)
import inspect
print(inspect.getdoc(the_answer))

isinstance(letter, str) = check if letter is a string

Every function should have a single responsibility

Refactoring is the process of improving code by changing it a little bit at a time

Immutable data types: int, float, bool, string, bytes. tuple, frozenset, None

Mutable data types: list, dict, set, bytearray, objects, functions, almost everything else

def foo(var=[]): # Mutable default arguments
    var.append(1)
    return var
foo()
foo()

A context manager is a type of function that sets up a context for your code to run in, runs your code, and then removes the context

The "open()" function is a context manager and does three things:

- when you write "with open()", it opens a fole that you can read from or write to;

- and it gives control back to your code so that you can perform operations on the file object

- removes the context by closing the file

with <context-manager>(<args>) as <variable-name>: #run your code

Statements in Python that have an indented block after them, like for loops, if/else statements, function definitions, etc. are called "compound statements".

with open('mt_file.txt') as my_file:
    text = my_file.read()
    length = len(text)
    
print('The file is {} characters long'.format(length))
# Open "alice.txt" and assign the file to "file"
with open('alice.txt') as file:
  text = file.read()

n = 0
for word in text.split():
  if word.lower() in ['cat', 'cats']:
    n += 1

print('Lewis Carroll uses the word "cat" {} times'.format(n))
Hidden output

That is because timer() is a context manager that does not return a value, so the as at the end of the with statement isn't necessary.

` image = get_image_from_instagram()

Time how long process_with_numpy(image) takes to run

with timer(): print('Numpy version') process_with_numpy(image)

Time how long process_with_pytorch(image) takes to run

with timer (): print('Pytorch version') process_with_pytorch(image) `

Two ways to define a context manager:

  1. Class-based
  2. Function-based

How to create a context manager:

  1. define a function;
  2. (optional) add any set up code your context needs;
  3. use the "yield" keyword to signal python that this is a special kind of function;
  4. Add the '@contextlib.contextmanager' decorator.

@contextlib.contextmanager def my_context(): print('hello') yield 42 -> when we write this word, it means that you are going to return a value print('goodbye') A context manager function is technically a generator that yields a single value

# Example of code that acces a database
@contextlib.contextmanager
def database(url):
    # set up database connection
    db = postgres.connect(url)
    
    yield db
    
    #tear down database connection
    db.disconnect()
    
url = 'http://datacamp.com/data'
with database(url) as my_db:
    course_list = my_db.execute(
        'SELECT * FROM courses'
    )