Functions are the foundation of structured programming , It's also the cornerstone of code reuse .Python Pass through def From defining functions . This article will explore Python The secret of function in .
In addition to user-defined functions ,Python There are some very useful functions built in :
Python Use in def To define a function , And use return To return a specific value .
Look at a simple example of a function :
def my_function(x, y, z): if z > 1: return z * (x + y) else: return z / (x + y) Copy code
Let's redefine the fiborach sequence as a function , It can be written like this :
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 use spaces or tab To indent .
stay Python in , We can set default values for parameters , In this way, if there is no parameter passed in the process of function call , The default value is used as the parameter .
The function we defined before my_function in , We can give z Set a default value :
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 You can just pass two parameters , final z You can use the default parameter values .
Be careful , The default is only executed once , If the parameter you pass in is a mutable object ( list , Dictionaries and class instances ) Words , We need to pay attention to this :
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 don't want to share the default values in subsequent calls , Then 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
We can use key=value Call the function in the same way .
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 this :
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 ,Python There are two kinds of arguments in a function , One is a parameter with a default value , One is parameters without default values .
Be careful , Parameters without default values must precede parameters with default values .
Look at an example of a mistake :
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 two ways to pass parameters to a function , One is delivery without keywords , One is delivery with keywords .
Be careful , Non keyword parameters must be passed before keyword parameters .
Take a wrong 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 here comes the question , If there are multiple keyword parameters and multiple non keyword parameters , Is there a simple way to define such a function ?
yes , we have , That's it *arguments
and **keywords
*arguments
To receive all the extra non keyword parameters . and **keywords
To receive all the extra keyword parameters .
Be careful ,
*arguments
Be sure to show up in**keywords
In front of .
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 this :
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
Will get the following results :
-- 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
Functions can pass parameters by location , You can pass parameters by keywords , You can also mix parameters .
In some cases , We may need to limit the type of parameters passed , For example, only receive by location delivery , Only receive by keyword delivery , Or just accept mixed delivery .
Look at 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
Be careful , Parameters are separated by / and * To make a distinction .
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
It defines 4 It's a parameter transfer function .
The first function is the standard form , It can be delivered by location , It can also be delivered by keywords .
The second function only allows passing by location .
The third function only allows passing by keyword .
The fourth function is mixed mode .
Sometimes we need to convert the values of a list or dictionary to the parameters of a function . Then you need to use the function of parameter unpacking .
*
The operator 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
**
The operator It 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
be familiar with java 's friends may know , stay JDK8 in ,Java Introduced Lambda expression . alike Python There are also Lambda.
You can take Lambda Think of it as an anonymous function . You can use it anywhere you need a function Lambda expression .
Take a look at a Lambda Example :
>>> def make_incrementor(n): ... return lambda x: x + n ... >>> f = make_incrementor(42) >>> f(0) 42 >>> f(1) 43 Copy code
Can also be 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
What we discussed before is a simple form of custom function , We don't know the parameter type and return value type of the function , In fact, functions can be written in more detail , This 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__
Attribute . We put a colon after the name of the parameter , Followed by an expression , Then the expression will be evaluated as the value of the label . For the return value , The definition of return value annotation is to add a combination symbol ->
, Followed by an expression , The annotation is located in the parameter list and represents def Between colons at the end of a 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 , More readable .