Block 3: Functions and Modules
Using Multi line Strings as Module Documentation
def foo(): """ This is the second line of the docstring. """
Defining a Lambda Function
lambda x: x The expression is composed of: The keyword: lambda A bound variable: x A body: x
Defining a Function
In Python a function is defined using the def keyword: def my_function(): pass
Yield in Detail
When the Python yield statement is hit, the program suspends function execution and returns the yielded value to the caller. (In contrast, return stops function execution completely.) When a function is suspended, the state of that function is saved. This includes any variable bindings local to the generator, the instruction pointer, the internal stack, and any exception handling.
reversed()
reversed() method returns an iterator that accesses the given sequence in the reverse order.
Using a Lambda Function
x = lambda a : a + 10 print(x(5))
Positional and Keyword Arguments
Python functions can contain two types of arguments: positional arguments and keyword arguments. Positional arguments must be included in the correct order. Keyword arguments are included with a keyword and equals sign.
Generator Expressions
>>> nums_squared_lc = [num**2 for num in range(5)] >>> nums_squared_gc = (num**2 for num in range(5)) The first object used brackets to build a list, while the second created a generator expression by using parentheses.
Constructing and Distributing Packages
A collection of modules ... and the documentation ... and the tests ... and any top-level scripts ... and any data files required ... and a way to build and install it...
Packages vs. Directories
A package is a collection of Python modules: while a module is a single Python file, a package is a directory of Python modules containing an additional __init__.py file, to distinguish a package from a directory that just happens to contain a bunch of Python scripts.
pyc file usage
A program doesn't run any faster when it is read from a '.pyc' or '.pyo' file than when it is read from a '.py' file; the only thing that's faster about '.pyc' or '.pyo' files is the speed with which they are loaded.
__init__.py file
A regular package is typically implemented as a directory containing an __init__.py file. When a regular package is imported, this __init__.py file is implicitly executed, and the objects it defines are bound to names in the package's namespace.
Return in Detail
A return statement is used to end the execution of the function call and "returns" the result (value of the expression following the return keyword) to the caller. The statements after the return statements are not executed. If the return statement is without any expression, then the special value None is returned.
Parameters vs. Arguments
From a function's perspective: A parameter is the variable listed inside the parentheses in the function definition. An argument is the value that is sent to the function when it is called.
Generator Function
Generator functions are a special kind of function that return a lazy iterator. These are objects that you can loop over like a list. However, unlike lists, lazy iterators do not store their contents in memory. Uses yield instead of return.
__name__ variable
If you are running your module (the source file) as the main program. The interpreter will assign the hard-coded string "__main__" to the __name__ variable.
Global Keyword
In Python, global keyword allows you to modify the variable outside of the current scope. It is used to create a global variable and make changes to the variable in a local context. c = 0 def add(): global c c = c + 2
*args and **kwargs
In Python, we can pass a variable number of arguments to a function using special symbols. There are two special symbols: *args (Non Keyword Arguments) **kwargs (Keyword Arguments) We use *args and **kwargs as an argument when we are unsure about the number of arguments to pass in the functions.
Recursion
In Python, we know that a function can call other functions. It is even possible for the function to call itself. These types of construct are termed as recursive functions.
Namespaces
Python scopes are implemented as dictionaries that map names to objects. These dictionaries are commonly called namespaces. These are the concrete mechanisms that Python uses to store names. They're stored in a special attribute called .__dict__.
map()
Returns a list of the results after applying the given function to each item of a given iterable (list, tuple etc.) # Return double of n def addition(n): return n + n # We double all numbers using map() numbers = (1, 2, 3, 4) result = map(addition, numbers) print(list(result))
Qualifying Entities with Module Names
Specifically, they must start with either a letter1 or an underscore and then be composed entirely of letters, digits2, and/or underscores. Modules should have short, all-lowercase names. Underscores can be used in the module name if it improves readability. Python packages should also have short, all-lowercase names, although the use of underscores is discouraged.
None keyword
The None keyword is used to define a null variable or an object. In Python, None keyword is an object, and it is a data type of the class NoneType.
Name Scopes
The Python scope concept is generally presented using a rule known as the LEGB rule. Local, Enclosing, Global, and Built-in scopes.
Import Directives
# Option 1 import random print(random.randint(1, 25)) # Option 2 from random import randint print(randint(1, 25)) # Using alias import math as m
Name hiding (shadowing)
In Python, we use double underscore (Or __) before the attributes name and those attributes will not be directly visible outside. # This line causes error print (myObject.__hiddenVariable)
Converting Generator Objects into Lists
Just use the list function. list(your_iterator)
pyc file creation
Pyc files are created by the Python interpreter when a .py file is imported. They contain the "compiled bytecode" of the imported module/program so that the "translation" from source code to bytecode (which only needs to be done once) can be skipped on subsequent imports if the .pyc is newer than the corresponding .py file, thus speeding startup a little. But it's still interpreted. Once the *.pyc file is generated, there is no need of *.py file, unless you edit it.
Invoking (Calling) a Function
To call a function, use the function name followed by parenthesis: my_function()
filter()
The filter() method filters the given sequence with the help of a function that tests each element in the sequence to be true or not. # function that filters vowels def fun(variable): letters = ['a', 'e', 'i', 'o', 'u'] if (variable in letters): return True else: return False # sequence sequence = ['g', 'e', 'e', 'j', 'k', 's', 'p', 'r'] # using filter function filtered = filter(fun, sequence) print('The filtered letters are:') for s in filtered: print(s)
reduce()
The reduce(fun,seq) function is used to apply a particular function passed in its argument to all of the list elements mentioned in the sequence passed along.This function is defined in "functools" module. # using reduce to compute maximum element from list print ("The maximum element of the list is : ",end="") print (functools.reduce(lambda a,b : a if a > b else b,lis))
Python Hashbangs
The shebang line in any script determines the script's ability to be executed like a standalone executable without typing python beforehand in the terminal or when double clicking it in a file manager (when configured properly). It isn't necessary but generally put there so when someone sees the file opened in an editor, they immediately know what they're looking at. Correct usage for Python 3 scripts is: #!/usr/bin/env python3
sort()
The sort() method sorts the list ascending by default.
sorted()
The sorted() function returns a sorted list of the specified iterable object. Note: You cannot sort a list that contains BOTH string values AND numeric values. Numbers as strings come before the characters.
Return vs. Yield Keywords
Yield indicates where a value is sent back to the caller, but unlike return, you don't exit the function afterward. Instead, the state of the function is remembered. That way, when next() is called on a generator object (either explicitly or implicitly within a for loop), the previously yielded variable num is incremented, and then yielded again.