------------
Here is a an example of a function:
>>> def fib(n): # write Fibonacci series up to n
... """Print a Fibonacci series up to n."""
... a, b = 0, 1
... while a < n:
... print(a, end=' ')
... a, b = b, a+b
... print()
...
>>> # Now call the function we just defined:
>>> fib(2000)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597
>>>
>>> fib.__doc__
Print a Fibonacci series up to n.
>>>
The keyword def introduces a function definition. It must be followed by the
function name and the parenthesized list of formal parameters. The statements
that form the body of the function start at the next line, and must be indented.
The first statement of the function body can optionally be a string literal;
this string literal is the function’s documentation string, or docstring. (More
about docstrings can be found in the section Documentation Strings.) There are
tools which use docstrings to automatically produce online or printed
documentation, or to let the user interactively browse through code; it’s good
practice to include docstrings in code that you write, so make a habit of it.
The execution of a function introduces a new symbol table used for the local
variables of the function. More precisely, all variable assignments in a
function store the value in the local symbol table; whereas variable references
first look in the local symbol table, then in the local symbol tables of
enclosing functions, then in the global symbol table, and finally in the table
of built-in names. Thus, global variables cannot be directly assigned a value
within a function (unless named in a global statement), although they
may be referenced.
The actual parameters (arguments) to a function call are introduced in the local
symbol table of the called function when it is called; thus, arguments are
passed using call by value (where the value is always an object reference, not
the value of the object). [1] When a function calls another function, a new
local symbol table is created for that call.
A function definition introduces the function name in the current symbol table.
The value of the function name has a type that is recognized by the interpreter
as a user-defined function. This value can be assigned to another name which can
then also be used as a function. This serves as a general renaming mechanism:
>>> fib
<function fib at 10042ed0>
>>> f = fib
>>> f(100)
0 1 1 2 3 5 8 13 21 34 55 89
Coming from other languages, you might object that fib is not a function but a
procedure since it doesn’t return a value. In fact, even functions without a
return statement do return a value, albeit a rather boring one. This value is
called None (it’s a built-in name). Writing the value None is normally
suppressed by the interpreter if it would be the only value written. You can see
it if you really want to using print():
>>> fib(0)
>>> print(fib(0))
None
>>>
It is simple to write a function that returns a list of the numbers of the
Fibonacci series, instead of printing it:
>>> def fib2(n): # return Fibonacci series up to n
... """Return a list containing the Fibonacci series up to n."""
... result = []
... a, b = 0, 1
... while a < n:
... result.append(a) # see below
... a, b = b, a+b
... return result # script terminates here, anything under will not be read
...
>>> f100 = fib2(100) # call it
>>> f100 # write the result
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
This example, as usual, demonstrates some new Python features:
- The return statement returns with a value from a function. return without an
expression argument returns None. Falling off the end of a function also
returns None.
- The statement result.append(a) calls a method of the list object result. A
method is a function that ‘belongs’ to an object and is named
obj.methodname, where obj is some object (this may be an expression), and
methodname is the name of a method that is defined by the object’s type.
Different types define different methods. Methods of different types may
have the same name without causing ambiguity. (It is possible to define your
own object types and methods, using classes, see Classes) The method
append() shown in the example is defined for list objects; it adds a new
element at the end of the list. In this example it is equivalent to
result = result + [a], but more efficient.
Default Arguments
-----------------
If you don't specify an argument to pass,
| # code def provide_or_ignore(a='no argument?'): return(a)
print(provide_or_ignore()) print(provide_or_ignore(a='now we are talking!')) no argument? now we are talking! |
Here is a more detailed example.
The function on the right can be called - only the mandatory argument: ask_ok('Do you really want to quit?') - mandatory argument + 1 of the optional arguments: ask_ok('OK to overwrite the file?', 2) - all arguments given: ask_ok('OK to overwrite the file?', 2, 'only yes or no!') | def ask_ok(prompt, retries=4, complaint='Yes or no, please!'): while True: ok = input(prompt) if ok in ('y', 'ye', 'yes'): return True if ok in ('n', 'no', 'nop', 'nope'): return False retries = retries - 1 if retries < 0: raise IOError('uncooperative user') print(complaint) |
The default value is evaluated at the point of function | # code i = 5 def f(arg=i): print(arg)
i = 6 f() |
Default value is evaluated only once. | # default value will accumulate between calls def f(a, L=[]): L.append(a) return L
print(f(1)) print(f(2)) print(f(3)) [1] [1, 2] [1, 2, 3]
# default value doesn't accumulate def f(a, L=None): if L is None: L = [] L.append(a) return L [1] [2] [3] |
Keyword Arguments
-----------------
- functions may accept arguments in the form of `kwarg=value`, `*kwarg`, or
`**kwarg`
- there are rules on how you can pass these to functions
This function accepts 1 required argument (voltage) and 3 optional arguments.
def parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue'):
print("-- This parrot wouldn't", action, end=' ')
print("if you put", voltage, "volts through it.")
print("-- Lovely plumage, the", type)
print("-- It's", state, "!")
It can be called in any of the following ways:
parrot(1000) # 1 positional argument
parrot(voltage=1000) # 1 keyword argument
parrot(voltage=1000000, action='VOOOOOM') # 2 keyword arguments
parrot(action='VOOOOOM', voltage=1000000) # 2 keyword arguments
parrot('a million', 'bereft of life', 'jump') # 3 positional arguments
parrot('a thousand', state='pushing up the daisies') # 1 positional, 1 keyword
It cannot be called using the ff:
parrot() # required argument missing
parrot(voltage=5.0, 'dead') # non-keyword argument after a keyword argument
parrot(110, voltage=220) # duplicate value for the same argument
parrot(actor='John Cleese') # unknown keyword argument
No argument may receive more than 1 value. Example:
>>> def function(a):
... pass
...
>>> function(0, a=0)
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: function() got multiple values for keyword argument 'a'
Using `*kwarg` allows the function to accept multiple arguments defined by the
user while `**kwarg` allows it to receive a dictionary (also defined by the
user).
# function
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)
keys = sorted(keywords.keys()) # this sort the user-defined dictionary
for kw in keys:
print(kw, ":", keywords[kw])
# calling the function
cheeseshop("Limburger", "It's very runny, sir.",
"It's really very, VERY runny, sir.",
shopkeeper="Michael Palin",
client="John Cleese",
sketch="Cheese Shop Sketch")
# output
-- 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.
----------------------------------------
client : John Cleese
shopkeeper : Michael Palin
sketch : Cheese Shop Sketch
Arbitrary Argument Lists
------------------------
- least frequently used method of passing arguments to a function
- this method also uses `*kwarg` -> variable number of arguments
- arguments will be wrapped inside a tuple
Zero or more normal arguments may occur before | def write_multiple_items(file, separator, *args): file.write(separator.join(args)) |
Any parameters appear after `*kwarg` must be | >>> def concat(*args, sep="/"): ... return sep.join(args) ... >>> concat("earth", "mars", "venus") 'earth/mars/venus' >>> concat("earth", "mars", "venus", sep=".") 'earth.mars.venus' |
Unpacking Argument Lists
------------------------
- argument lists may be generated by unpacking a list or a dictionary
Unpacking a list | >>> 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] |
Unpacking a dictionary | >>> 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) -- This parrot wouldn't VOOM if you put four million volts through it. E's bleedin' demised ! |
Lambda Expressions
------------------
- special type of functions that return a function
- doesn't include a `return` statement -- always contains an expression that is
always returned
- see example uses below
Getting the sum of 2 numbers | >>> sum = lambda x, y : x + y >>> sum(3,4) 7 >>> |
Lambda functions can also reference | >>> def make_incrementor(n): ... return lambda x: x + n ... >>> f = make_incrementor(42) >>> f(0) 42 >>> f(1) 43 |
Passes a small function as an | >>> 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')] |
Others | # The lambda keyword in Python provides a # shortcut for declaring small and # anonymous functions:
>>> add = lambda x, y: x + y >>> add(5, 3) 8
# You could declare the same add() # function with the def keyword:
>>> def add(x, y): ... return x + y >>> add(5, 3) 8
# So what's the big fuss about? # Lambdas are *function expressions*: >>> (lambda x, y: x + y)(5, 3) 8
# • Lambda functions are single-expression # functions that are not necessarily bound # to a name (they can be anonymous).
# • Lambda functions can't use regular # Python statements and always include an # implicit `return` statement. |
Documentation Strings aka docstrings
------------------------------------
- docstrings are string literals that describe your code
- see below the format, examples, and rules in writing them
A single line docstring | >>> >>> def test(): ... """just a sample""" # first line must be short and concise summary ... # of your code's purpose >>> test.__doc__ 'just a sample' >>> |
If more than 1 line is required, you | >>> def my_function(): ... """Do nothing, but document it. ... ... No, really, it doesn't do anything. ... You may use this function without harm ... """ ... pass ... >>> print(my_function.__doc__) Do nothing, but document it.
No, really, it doesn't do anything. |
Some examples of common docstrings | >>> print(len.__doc__) Return the number of items in a container. >>> >>> >>> print(map.__doc__) map(func, *iterables) --> map object
Make an iterator that computes the function using arguments from each of the iterables. Stops when the shortest iterable is exhausted. >>> >>> print(filter.__doc__) filter(function or None, iterable) --> filter object
Return an iterator yielding those items of iterable for which function(item) is true. If function is None, return the items that are true. >>> |
Function Annotations
--------------------
- ways of describing function arguments
- has no effect on the code execution
- not commonly used
- annotations are stored in `__annotations__` attribute of the function
In this examle, a has no annotation, b is | >>> def foo(a, b: 'a string', c: int) -> float: ... print(a + b + c) |
Using the example above, we can see here | >>> foo('Hello', ', ', 'World!') Hello, World! >>> >>> foo(1, 2, 3) 6 >>> |
A complex example with "eggs" being | >>> def f(ham: 42, eggs: int = 'spam') -> "Nothing to see here": ... print("Annotations:", f.__annotations__) ... print("Arguments:", ham, eggs) ... >>> f('wonderful') Annotations: {'eggs': <class 'int'>, 'return': 'Nothing to see here', 'ham': 42} Arguments: wonderful spam |
Future Statements
-----------------
- Used in Python 2.X to support Python 3.X syntax
Allows Python 2.X to use `print('hello')` together with `print "hello"` | from __future__ import print_function |
No comments:
Post a Comment