[Python] function and function programming

Source: Internet
Author: User
Tags class definition closure function definition wrapper

1. Functions

Use DEF statements to define functions:

def add(x, y):    return x + y

A function body is a series of statements that are executed when a function is called. The method of calling a function is to add a parameter after the function name. The order of the arguments must match the function definition, or the TypeError exception will be thrown. You can set default values for the parameters of a function, for example:

def split(line, delimiter=‘,‘):    statements

If you add an asterisk "*" to the last parameter name, the function can accept any number of arguments:

def fprintf(file, fmt, *args):    file.write(fmt % args)fprintf(out, "%d %s %f", 42, "hello world", 3.45)

In this example, all the remaining arguments are put into the args variable as a tuple. To pass the tuple args as a parameter to a function, you can use the *args syntax in a function call. For example:

def printf(fmt, *args):    fprintf(sys.stdout, fmt, *args)

There is also a way to provide a function parameter, that is, to name each parameter and specify a value for it, which is called a keyword parameter, for example:

def foo(w, x, y, z):    statementsfoo(x=3, y=22, w=‘hello‘, z=[1, 2])

When using keyword parameters, the order of the parameters does not matter. However, unless a default value is provided, all required function arguments must be explicitly named. Positional and keyword parameters can be used at the same time, provided that all positional parameters must first appear, providing values for all non-optional parameters, such as:

foo(‘hello‘, 3, z=[1, 2], y=22)

If the last parameter of the function definition starts with "* *", you can put all the extra keyword arguments into a dictionary and pass the dictionary to the parameter. For example:

def make_table(data, **params):    fgcolor = params.pop("fgcolor", "black")    bgcolor = params.pop("bgcolor", "white")    width = params.pop("width", None)    if params:        raise TypeError("Unsupported configuration options %s" % list(params))make_table(items, fgcolor="black", bgcolor="white", border=1, borderstyle="grooved", cellpoadding=10, width=400)

The keyword and variable-length parameter lists can be used together, as long as the "* *" parameter appears at the end, for example:

def spam(*args, **kwargs):    statements

?

2. Parameter passing and return value

When a function is called, the function argument simply refers to the name of the incoming object. The basic semantics of parameter passing are not exactly the same as those known in other programming languages, such as "pass by value" and "pass by reference". For example, by passing immutable values, the parameters appear to be actually passed by value, and if you pass a Mutable object (such as a list or dictionary) to a function and then modify the Mutable object, the changes are reflected in the original object. For example:

a = [1, 2, 3, 4, 5]def square(items):    for i, x in enumerate(items):        items[i] = x * xsquare(a) # a = [1, 4, 9, 16, 25]

The return statement returns a value from the function. If no value is specified or the return statement is omitted, the None object is returned. If there are multiple return values, you can put them in a tuple, for example:

def factor(a):    d = 2    while (d <= (a / 2)):        if ((a / d) * d == a):            return ((a / d), d)        d = d + 1    return (a, 1)

?

3. Scope rules

Each time a function is executed, a new local namespace is created. The namespace represents a local environment that contains the name of the function parameter and the variable name that is assigned in the function body. When these names are parsed, the interpreter first searches the local namespace. If no matching name is found, it searches the global namespace. If no matching values are found in the global namespace, the built-in namespaces are eventually checked. If it is still not found, a Nameerror exception is thrown.
One of the attributes of a namespace is the operation of a global variable in a function, such as:

a = 42def foo():    a = 13foo() # a仍然是42

When executing this code, try to modify the value of variable A in function foo, but eventually a is still 42. When variables are assigned in a function, they are always bound to the local namespace of the function, so the variable A in the body of the function refers to a new object that contains the value 13, not an external variable. Using the global statement can change this behavior, for example:

a = 42def foo():    global a    a  = 13foo() # a的值已变13

Python supports nested function definitions, such as:

def countdown(start):    n = start    def display():        print(‘T-minus %d‘ % n)    while n > 0:        display()        n -= 1

Use static scopes to bind variables in a nested function, that is, when the name is resolved, the local scope is first checked, and then the scope defined by the outer nested function is checked by an inward layer. If no match is found, the global namespace and the built-in namespace will be searched at the end. You can use the Nonlocal statement to bind external variables, for example:

def countdown(start):    n = start    def display():        print(‘T-minus %d‘ % n)    def decrement():        nonlocal n        n -= 1    while n > 0:        display()        decrement()

Instead of binding a name to a local variable defined in any function, the Nonlocal declaration searches the next layer of function definition in the current call stack, the dynamic scope. For example:

i = 0def foo():    i = i + 1 # UnboundLocalError异常

Although there is a global variable I, it does not give a value to the local variable i. The function definition determines whether the variable is local or global, and does not suddenly change its scope in the function.

?

4. Function object and Closure

The function is the first class of objects in Python. That is, they can be passed as arguments to other functions, placed in data structures, and returned as functions. For example:

def callf(func):    return func()

When a function is treated as data, it explicitly carries information related to the surrounding environment that defines the function. This affects how free variables are bound in the function. For example:

# foo.pyx = 42def callf(func):    return func()# main.pyimport foox = 37def helloworld():    reutrn "x is %d" % xfoo.callf(helloworld) # x is 37

In the example above, even if a variable x is defined in foo.py, the variable calls the value defined in the same environment as the HelloWorld () function. When the statements that make up a function are packaged together with the execution environment of those statements, the resulting object is called a closure. In fact, all functions have a __globals__ property that points to the global namespace that defines the function. For example:

def page(url):    def get():        return urlopen(url).read()    return getpython = page("http://www.python.org")jython = page("http://www.jython.org")pydata = python() # 获取http://www.python.orgjydata = jython() # 获取http://www.jython.org

?

5. Decorative Device

An adorner is a function whose main purpose is to wrap another function or class. The primary purpose of this packaging is to transparently modify or enhance the behavior of the wrapped object. The syntax that represents the adorner is the special symbol "@", for example:

@tracedef square(x):    return x * x

The above code can be simplified to:

def square(x):    return x * xsquare = trace(square)

Now consider the implementation of trace:

enable_tracing =  Trueif enable_tracing:    debug_log = open("debug.log", "w")def trace(func):    if enable_tracing:        def callf(*args, **kwargs):            debug_log.write("Calling %s: %s, %s\n" % (func.__name__, args, kwargs))            r = func(*args, **kwargs)            debug_log.write("%s returned %s\n" % (func.__name__, r))            return r        return callf    else:        return func

In this Code, trace () creates a wrapper function that writes some debug output, and then invokes the original function object. So if you call the square () function, you see the output of the write () method in the wrapper.
When using adorners, they must appear on a separate line before the function or class definition. You can use multiple adorners at the same time, such as:

@foo@bar@spamdef grok(x):    passgrok = foo(bar(spam(grok)))

Adorners can also accept parameters, such as:

@eventhandler(‘BUTTON‘)def handle_button(msg):    ...@eventhandler(‘RESET‘)def handle_reset(msg):    ...

If parameters are supplied, the adorner's semantics are as follows:

def handle_button(msg):    ...temp = eventhandler(‘BUTTON‘)handle_button = temp(handle_button)

For class adorners, you should have the adorner function always return the class object as the result. Code that requires the use of the original class definition may refer directly to the class member.
?

6. Generator and yield

The function uses the yield keyword to define the generator object. A generator is a function that generates a sequence of values for use in iterations, for example:

def countdown(n):    while n > 0:        yield n        n -=1    return

If the function is called, and the code in it does not start executing, it returns a generator object that is called in _next_(), for example:

c = countdown(10)c.__next__()

When you call _next_(), the generator function executes the statement continuously until the yield statement is encountered. The _next_() method is not normally called directly on the generator, but is used in a for statement, sum (), or some other operation that uses a sequence, for example:

for n in countdown(10):    statementsa = sum(countdown(10))

The flag for the generator function to complete is to return or throw an stopiteration exception, which marks the end of the iteration. If the generator is not fully completed and is no longer in use, you can call the close () method, although it is usually not necessary to call it, for example:

c = countdown(10)c.__next__()c.close()c.__next__() # 抛出异常

Inside the generator function, the close () method is called when a Generatorexit exception occurs on the yield statement. You can choose to get this exception, for example:

def countdown(n):    try:        while n > 0:            yield n            n -= 1    except GeneratorExit:        print("Only made it to %d" % n)

?

7. Association and yield expressions

Within a function, the yield statement can also be used to make an expression to the right of the current assignment operator, for example:

def receiver():    while True:        n = (yield)        print("Got %s" % n)

A function that uses the yield statement in this way is called a co-process, and it executes in response to the value sent to it. It behaves similarly to generators, such as:

r = receiver()r.__next__()r.send(1)r.send(2)

In the process, the first call to _next_() is easy to forget and can be wrapped using an adorner that automatically completes the step, for example:

def coroutine(func):    def start(*args, **kwargs):        g = func(*args, **kwargs)        g.next()        return g    return start@coroutinedef receiver():    while True:        n = (yield)        print("Got %s" % n)r = receiver()r.send("Hello World")

The run of the process is generally indefinite, unless it is explicitly closed or exits on its own. Use Close () to turn off the flow of input values, for example:

r.close()r.send() # 抛出异常

If you continue to send a value to the coprocessor after it is closed, a Stopiteration exception is thrown, and the close () operation throws an Generatorexit exception inside the thread.
?

8. The list contains

A common operation of a function is to apply a function to all items in a list and create a new list using the result. This is a common operation, so there are operators called List derivations, such as:

nums = [1, 2, 3, 4, 5]squares = [n * n for n in nums]

The general syntax for list derivation is as follows:

[expression for item1 in iterable1 if condition1                                        for item2 in iterable2 if condition2                                        ...                                        for itemN in iterableN if conditionN]

Here are a few examples:

a = [-3, 5, 2, -10, 7, 8]b = ‘abc‘c = [2 * s for s in a] # c = [-6, 10, 4, -20, 14, 16]d = [s for s in a if s >= 0] # d = [5, 2, 7, 8]e= [(x, y) for x in a                                for y in b                                if x > 0] # e = [(5, ‘a‘), (5, ‘b‘), (5, ‘c‘),                    (2, ‘a‘), (2, ‘b‘), (2, ‘c‘),                    (7, ‘a‘), (7, ‘b‘), (7, ‘c‘),                    (8, ‘a‘), (8, ‘b‘), (8, ‘c‘)]f = [(1, 2), (3, 4), (5, 6)]g  = [math.sqrt(x * x + y * y) for x, y in f] # g = [2.23606797749979, 5.0, 7.810249675906654]

?

9. Generator expressions

A builder expression is an object that performs a calculation that is the same as a list, but produces a result iteratively, with the same syntax as the list, except with parentheses instead of square brackets, as follows:

(expression for item1 in iterable1 if condition1                                        for item2 in iterable2 if condition2                                        ...                                        for itemN in iterableN if conditionN)

The generator expression does not actually create a list or immediately evaluates an expression within parentheses, creating a generator object that iterates through and generates values as needed, for example:

a  = [1, 2, 3, 4]b = (10 * i for i in a)print(b.__next__())print(b.__next__())

When using list derivation, Python actually creates a list that contains the result data. When using a builder expression, Python creates a generator that knows only how to generate data as needed. In some applications, performance and memory usage can be impacted, such as:

f = open("data.txt")lines = (t.strip() for t in f)comments = (t for t in lines if t[0] == ‘#‘)for c in comments:    print(c)

A builder expression does not create an object in a sequential form and cannot be indexed. However, you can use the built-in list () function to convert a generator expression to a list, for example:

clist = list(comments)

?

Ten. Lambda operators

Use a lambda statement to create an anonymous function in the form of an expression:

lambda args: expression

Args is a comma-separated list of arguments, and expression is an expressions that use these arguments, for example:

a = lambda x, y: x + yr = a(2, 3)

Code defined with a lambda statement must be a valid expression. Multiple statements and other non-expression statements, such as for or while, cannot appear in a lambda statement.
?

11. Document String

Typically, the first statement of a function uses a document string that describes the purpose of the function, for example:

def factorial(n):    """Computes n factorial. For examples:            >>> factorial(6)            120    """    if n <= 1: return 1    else: return n* factorial(n-1)

The document string is stored in the function's __doc__ property, which the IDE typically uses to provide interactive help. If you need to use adorners, you might break the help features associated with document strings, such as:

def wrap(func):    call(*args, **kwargs):        return func(*args, **kwargs)    return call@wrapdef factorial(n):    """Computes n factorial."""

If you look for help with the above function, you may see a rather strange solution, which is to write an adorner function that can pass the function name and document string, for example:

def wrap(func):    call(*args, **kwargs):        return func(*args, **kwargs)    call.__doc__ =  func.__doc__    call.__name__ = func.__name__    return call

Because this is a common problem, the Functools module provides the function wraps, which is used to automatically replicate these properties, for example:

from functools import wrapsdef wrap(func):    @wrap(func)    call(*args, **kwargs):        return func(*args, **kwargs)    return call

?

12. Function Properties

You can add any property to the function, for example:

def foo():    statementsfoo.secure = 1foo.private = 1

The function property is stored in the __dict__ property of the function, and the __dic__ property is a dictionary. As with the document string, be aware of the mixed use of function properties and adorners. If you use the adorner wrapper function, the property is actually accessed by the adorner function rather than the original function.
?

Eval (), exec (), and compile () functions

The eval (str [, Globals [, locals]) function executes an expression string and returns the result, for example:

a = eval(‘3 * math.sin(3.5 + x) + 7.2‘)

Similarly, the EXEC (str [, Globals [, locals]) function executes a string containing arbitrary python code. For example:

a = [3, 5, 10, 13]exec("for i in a: print(i)")

Both of these functions are executed in the caller's namespace. The eval () and EXEC () functions can accept one or two optional mapping objects, respectively, as global and local namespaces for code execution, such as:

globals = {‘x‘: 7, ‘y‘: 10, ‘birds‘: [‘Parrot‘, ‘Swallow‘, ‘Albatross‘]}locals = {}a = eval("3 * x + 4 * y", globals, locals)exec("fro b in birds: print(b)", globals, locals)

The compile (str, filename, kind) function compiles a string into bytecode, where Str is a string containing the code to be compiled, and filename is the file that defines the string, and the kind parameter specifies the type of code to compile. Single represents a statement, and exec represents a set of statements, and Eval represents an expression. For example:

s = "for i inrange(0, 10): print(i)"c = compile(s, ‘‘, ‘exec‘)exec(c)s2 = "3 * x + 4 * y"c2 = compile(s2, ‘‘, ‘eval‘)result = eval(c2)

[Python] function and function programming

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.