Python Basics: Functions

brief introduction

Function is not only the basis of structured programming, but also the cornerstone of code reuse. Python uses def to customize functions. This article will explore the secrets of functions in Python.

Built in function

In addition to user-defined functions, Python has built-in some very useful functions:

Custom function

Python uses def to define functions and return to return specific values.

Take a simple function example:

def my_function(x, y, z):
      if z > 1:
         return z * (x + y)
     else:
         return z / (x + y)
Copy code

The example of fiborah sequence we talked about earlier is redefined by function, which can be written as follows:

def fib(n):   
     a, b = 0, 1
     while a < n:
         print(a, end=' ')
         a, b = b, a+b
     print()
     
# Call function
fib(1000)
Copy code

The contents of the function need to be indented with spaces or tab s.

Default values for parameters

In Python, we can set the default value for the parameter, so that if no parameter is passed during the function call, the default value will be used as the parameter.

The function my we defined earlier_ In function, we can set a default value for z:

def my_function(x, y, z=10):
      if z > 1:
         return z * (x + y)
     else:
         return z / (x + y)
Copy code

So we're calling my_function can only pass two parameters, and the last z can use the default parameter value.

Note that the default value will be executed only once. If the parameters you pass in are variable objects (lists, dictionaries and class instances), we need to pay attention to this problem:

def f(a, L=[]):
    L.append(a)
    return L

print(f(1))
print(f(2))
print(f(3))

# output
[1]
[1, 2]
[1, 2, 3]
Copy code

If you do not want to share the default value in subsequent calls, you can put the assignment of the default value inside the function body:

def f(a, L=None):
    if L is None:
        L = []
    L.append(a)
    return L
 Copy code

Keyword parameters

We can call the function with key=value.

Or the previous function:

def my_function(x, y, z=10):
      if z > 1:
         return z * (x + y)
     else:
         return z / (x + y)
Copy code

We can call:

my_function(1,y=3,z=5)
my_function(1,y=3)
Copy code

But it can't be used like this:

my_function(y=3,1)
Copy code

Keyword parameters must be placed after non keyword parameters. You cannot assign a parameter more than once:

>>> def function(a):
...     pass
...
>>> function(0, a=0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: function() got multiple values for keyword argument 'a'
Copy code

From the above discussion, we can see that there are two parameters in Python functions, one with default value and the other without default value.

Note that parameters without default values must precede those with default values.

Take a wrong example:

In [69]: def fa(a=100,b,c=200):
    ...:     pass
  File "<ipython-input-69-d5678b64f352>", line 1
    def fa(a=100,b,c=200):
          ^
SyntaxError: non-default argument follows default argument
 Copy code

There are also two ways to pass parameters to functions, one is without keywords, and the other is with keywords.

Note that non keyword parameters must be passed before keyword parameters.

For example:

In [70]: def fa(a,b=100,c=200):
    ...:     pass
    ...:

In [71]: fa(a=100,30)
  File "<ipython-input-71-5a229b8e420e>", line 1
    fa(a=100,30)
            ^
SyntaxError: positional argument follows keyword argument
 Copy code

So the question is, if there are multiple keyword parameters and multiple non keyword parameters, is there a simple way to define such a function?

Yes, they are arguments and keywords

arguments is used to receive all redundant non keyword parameters. keywords is used to receive all additional keyword parameters.

Note that * arguments must appear before * * keywords.

for instance:

def cheeseshop(kind, *arguments, **keywords):
    print("-- Do you have any", kind, "?")
    print("-- I'm sorry, we're all out of", kind)
    for arg in arguments:
        print(arg)
    print("-" * 40)
    for kw in keywords:
        print(kw, ":", keywords[kw])
Copy code

We can call:

cheeseshop("Limburger", "It's very runny, sir.",
           "It's really very, VERY runny, sir.",
           shopkeeper="Michael Palin",
           client="John Cleese",
           sketch="Cheese Shop Sketch")
Copy code

The following results will be obtained:

-- Do you have any Limburger ?
-- I'm sorry, we're all out of Limburger
It's very runny, sir.
It's really very, VERY runny, sir.
----------------------------------------
shopkeeper : Michael Palin
client : John Cleese
sketch : Cheese Shop Sketch
 Copy code

Special parameters

Functions can pass parameters by location, keyword, or mixed.

In some cases, we may need to limit the types of parameters passed, such as receiving only positional pass, only keyword pass, or only mixed pass.

See the definition of special parameters:

def f(pos1, pos2, /, pos_or_kwd, *, kwd1, kwd2):
      -----------    ----------     ----------
        |             |                  |
        |        By location or keyword           |
        |                                - Only passing by keyword is allowed
         -- Only passing by location is allowed
 Copy code

Note that the parameters are distinguished by / and *.

Let's take an example:

>>> def standard_arg(arg):
...     print(arg)
...
>>> def pos_only_arg(arg, /):
...     print(arg)
...
>>> def kwd_only_arg(*, arg):
...     print(arg)
...
>>> def combined_example(pos_only, /, standard, *, kwd_only):
...     print(pos_only, standard, kwd_only)
Copy code

Functions with four parameter transfer modes are defined above.

The first function is the standard form, which can be passed by location or keyword.

The second function only allows passing by location.

The third function only allows passing by keyword.

The fourth function is mixed mode.

Parameter unpacking

Sometimes we need to convert the values of a list or dictionary to the parameters of a function. Then you need to use the parameter unpacking function.

*Operators can be used to unpack lists and tuples.

>>> list(range(3, 6))            # normal call with separate arguments
[3, 4, 5]
>>> args = [3, 6]
>>> list(range(*args))            # call with arguments unpacked from a list
[3, 4, 5]
Copy code

**Operators can be used to unpack dictionaries.

>>> def parrot(voltage, state='a stiff', action='voom'):
...     print("-- This parrot wouldn't", action, end=' ')
...     print("if you put", voltage, "volts through it.", end=' ')
...     print("E's", state, "!")
...
>>> d = {"voltage": "four million", "state": "bleedin' demised", "action": "VOOM"}
>>> parrot(**d)
Copy code

Lambda

Friends familiar with Java may know that in JDK8, Java introduces Lambda expressions. Similarly, there is Lambda in Python.

You can think of Lambda as an anonymous function. You can use Lambda expressions wherever you need functions.

Take an example of Lambda:

>>> def make_incrementor(n):
...     return lambda x: x + n
...
>>> f = make_incrementor(42)
>>> f(0)
42
>>> f(1)
43
 Copy code

You can also take the return value of lambda as a parameter:

>>> pairs = [(1, 'one'), (2, 'two'), (3, 'three'), (4, 'four')]
>>> pairs.sort(key=lambda pair: pair[1])
>>> pairs
[(4, 'four'), (1, 'one'), (3, 'three'), (2, 'two')]
Copy code

Function annotation

We discussed the simple custom function form before. We don't know the parameter type and return value type of the function. In fact, the function can be written in more detail, which requires function annotation.

The so-called function annotation is the optional metadata information of the type in the user-defined function.

Function labels are stored in the form of dictionaries__ annotations__ Property. If we add a colon to the name of the parameter followed by an expression, the expression will be evaluated as the value of the label. For the return value, the definition of the return value label is to add a combination symbol - >, followed by an expression. The label is located between the formal parameter list and the colon indicating the end of the def statement.

for instance:

>>> def f(ham: str, eggs: str = 'eggs') -> str:
...     print("Annotations:", f.__annotations__)
...     print("Arguments:", ham, eggs)
...     return ham + ' and ' + eggs
...
>>> f('spam')
Annotations: {'ham': <class 'str'>, 'return': <class 'str'>, 'eggs': <class 'str'>}
Arguments: spam eggs
'spam and eggs'
Copy code

In fact, the program written with function annotation is clearer and more readable.

 

Keywords: Python Back-end

Added by levi_501_dehaan on Fri, 07 Jan 2022 10:29:11 +0200