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))
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:
- Class-based
- Function-based
How to create a context manager:
- define a function;
- (optional) add any set up code your context needs;
- use the "yield" keyword to signal python that this is a special kind of function;
- 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'
)