Low Orbit Flux Logo 2 F

Python - Functions

Functions allow you to define a block of code that can be called over and over again. They can be passed parameters. They also return a value. If no return value is specified they will return avalue of None.

Functions can be defined like this.



def test1():
    x + 5 + 4
    print(x)

You can use parameters like this:



def test1(x):
    x += 5
    print(x)

Call a fuction like this:



test1(4)

You can assign a function to a variable and use that as an alias or alternate name for the same function:



t = test1
t(3)

Here is an example using a return value:



def test1(x):
    x += 5
    return x

Using return without a param or ommitting return will result in None being returned. Here is an example that eturns none:



def test1(x):
    pass
    return

You can specify default argument values for parameters:



def test2(name, count=5, description='A silly value.'):
    pass

test2('Steve')
test2('y', 7)
test2('y', 2, "A serious description.")

If you use a variable for a default value it will be evaluated at the time of fuction definition.



i = 9
def test2(x=i):
    print(x)

i = 4
test2()  # still prints 9

Default values set in a function definition are evaluated only once. For example, values are added to L every time this is called:



def test1(v, a=[]):
    a.append(v)
    return a

You can avoid this by using a new list every time:



def test1(v, a=None):
    if a is None:
        a = []
    a.append(v)
    return a

Keyword Arguments

Python functions can use keyword arguments in addtion to positional arguments.



def load_data(count, status='a stiff', format='voom', color='Norwegian Blue'):
    print("Format: ", format)
    print("Count: ", count)
    print("Color: ", color)
    print("Status: ", status)

Valid:



load_data(123)                           # 1 positional arg
load_data(count=123)                     # 1 keyword arg
load_data(count=123, format='compact')   # 2 keyword arg
load_data(format='compact', count=123)   # 2 keyword arg
load_data(123, 'frozen', 'compact')      # 3 positional arg
load_data(123, status='melted')          # 1 positional, 1 keyword
load_data(123, status='melted')          # 1 positional, 1 keyword

Not valid:



load_data()                       # missing non-optional argument
load_data(format="a", 5)          # positional argument after keyword argument
load_data(123, count=456)         # duplicate aregument specified
load_data(category='mechanical')  # undefined keyword argument

Arbitrary Argument Lists

**name will hold a dictionary with all keyword args that aren’t formal args
*name tuple containing all positional args that aren’t formal args


def test3(x, *y, **z):
    print("Value: ", x)
    for i in y:
        print(i)
    for i in z:
        print(i, ":", z[i])


test3("a", "b", "c", type="x", status="y", value="z")

Python function keyword and positional arguments

If the name of an arg passed as a packed arg list conflicts with the name of a positional arg, this is totally fine and will work without ambiguity. This is a little bit strange and feels wrong but it isn’t. See this example below.



def test4(x, /, **kwds):
    return 'x' in kwds

z = test4(2, **{'x': 3})

print(z)    # will print 3 not 2

Positional only is good for when:

Unpacking Argument Lists

You can pass an argument list like this and it will be unpacked:



def test1( a, b, c ):
    print(a, b, c)

x = ('x', 'y', 'z')
test1(*x)

You can also basically pass a dictionary of keyword arguments like this:



def test2( a, b, c ):
    print(a, b, c)

x2 = {"a": "x", "b": "y", "c": "z"}
test2(**x2)

Unpack and pack - you can do this too:



def test3( *a ):
    print(a)
test3(*x)

Lambda Expressions

To create a lambda, specify any variables, then a colon, then an expression. The expression can include conditionals. What ever the expression returns is what the lambda will return.

Here are a few lambda examples.



a = lambda : print('test')
b = lambda a: a + 5
c = lambda a,b: a * b + 5

d = lambda a: "larger" if a > 5 else "smaller"

e = lambda a,b: b - 1 if a > 5 else b + 1

print(a())
print(b(3))
print(c(3,5))

print(d(2))
print(d(7))

print(e(1,2))
print(e(7,2))

You can create a function that dynamically generates another function as a lambda.



def test1(n):
    return lambda x: x + n

x = test1(42)
x(0)
x(1)

Function Annotations

Function annotations are another interesting feature. You can use these to do the following:

Here is an example:



def test3(a: str, b: str = 'xyz') -> str:
    print("Annotations: ", test3.__annotations__)
    print("Args:", a, b)
    return a + ' ' + b

Documentation

You will generally specify documentation for a function as a doc string at the beginning of the function definition.

Documentation string example:



def test3():
    """Important function to process data.

    This function exists to process data.
    Here we cover the specifics and everything
    that you need to know.
    """
    pass

print(test3__doc__)