Dark theme

Key Ideas


The key ideas for this part centre on making functions and making sure others can use your functions.


Functions

The simplest function looks like this:

def function_name ():
    # Do stuff.

Which is then called, thus:

function_name()

To send data in, set up the function like this:

def function_name (variable_to_receive_data):
    # Do stuff.

And call it, thus:

function_name(data_to_send_in)

To send data back, set up the function like this:

def function_name (variable_to_receive_data):
    return some_answer

If the function returns something, you have to either receive it with a variable label, or pass it on to another function:

a = function_name(data_to_send_in)
print(function_name(data_to_send_in))

Example

def get_circle_area (radius):
    return 3.14 * (radius * radius)

a = get_circle_area(21)
print(str(get_circle_area(21)))


Multiple parameters

You can have multiple parameters allowing multiple data arguments to be sent in.

Parameters can be positional (allocated based on their order); have default values; accept multiple single values as a tuple; be forced to have names that must be used as keyword arguments; and to accept multiple keywords. Here's an example using all of these:

def function(param1, param2, param3="default", *pp, keyword_param1="default2", keyword_param2, **kp):
    pass

function(1,2,3,4, keyword_param1=5, keyword_param2=6, keyword_param3=7)

Comments:

param1, param2, param3="default" are positional parameters. As soon as param3="default" has a default value, any new positional parameters to its right would have to also have default values (though not keyword parameters).

*pp Picks up any remaining non-keyword arguments passed in. These have to be to the left of any keyword arguments. After *pp everything has to be keyworded.

keyword_param1="default2", keyword_param2 are keyword parameters. Note that unlike positional parameters, they do not consistently need defaults once one has been given, as there is no ambiguity as to which is meant.

**kp Picks up any additional keyword arguments sent in as a dict.

Note that one can force the use of keywords by having a tuple variable like *pp that forces anything after it to be keywords, and then by not including defaults. Infact, you don't even need to name the tuple, thus:

def function (*, keyword1, keyword2):

This function will demand its arguments are kwargs and present.


*is known as the iterable unpacking operator. It can also be used to unpack tuples in expressions or function calls:

a = [1,2,3,4]
answer = some_function_taking_in_positional_variables(*a)
a = [10,20]
answer = some_function_taking_in_positional_variables(1,*a, 2) # Note the use can, as here, be in the middle.

**is known as the dictionary unpacking operator. It can also be used to unpack dicts in expressions or function calls:

d = {"first":"George","surname":"Formby"}
some_function_taking_in_kwargs("5",**d)


Scope

In general, variables can be seen in the blocks they are assigned a value, and all nested blocks within that block (where they are known as "free variables"). However, one has to remember that as soon as an variable is assigned (if it is not inside a variable with mutable content) it becomes a new variable. At that point, the "scope" (where the variable can be seen) closes in to wherever the assignment is made. To see this, here's an example:

a = 10
b = [10]
c = [10]

def f1():
    a = 11
    b = [11]
    c[0] = 11

f1()
print(a) # prints 10
print(b) # prints [10]
print(c[0]) # prints 11

To maintain a variable with the same name as the same label inside a block despite allocation, you need to use either the global keyword (if the variable is first used outside any function) or nonlocal if it is defined in a block which the current block is nested in.


Style and Documentation

A few community style rules (for other style details, see PEP 8):

Use 4 spaces per indent, rather than tabs (this can be set up in IDEs).

Use blank lines before function defs, and to separate logical code units.

Use the following styles for different elements: function_names; variable_names; ClassNames; modulename; CONSTANT_NAMES
(A constant is a variable you don't want changed in value)

Keep lines to 79 characters or less; that is:
aaaaaaaaaa aaaaaaaaaa aaaaaaaaaa aaaaaaaaaa aaaaaaaaaa aaaaaaaaaa aaaaaaaaaa aaaaaaaaa

Spaces around operators and after commas, but not immediately just inside (){}[]:
a = (1, 2)

Indent comments to the level of the code referred to.

Example doc strings (for style details, see PEP 257):

def add(num1, num2):
    """Add two numbers."""

def add (num1, num2):
    """
    Add two numbers.

    Keyword arguments:
    num1 -- an integer or double number (no default)
    num2 -- an integer or double number (no default)
    """

    return num1 + num2