Python function Summary-decorator and lambda

Source: Internet
Author: User

Python function Summary-decorator and lambda
This article is still a learning note. The structure of this article first talks about the decorator and then lambda expressions. The decorator has many contents. First, the decorator syntax is briefly introduced, and then the details that should be noted when understanding and using the decorator without parameters are described in detail, then a simple cache decorator is implemented as a practice. Finally, on the basis of understanding the decorator without parameters, the details that need to be noticed when understanding and using the decorator with parameters are introduced. Lambda expressions focus on usage details and understanding. If something is wrong, please correct it. In fact, it is very easy to understand the function of the decorator. This is probably the case when you look at the chapters related to core python. In actual application, I found it difficult to decide how to use the decorator by intuition, especially the decorator with parameters. So I thought about it and wrote some experiences. For the sake of completeness, the decorator syntax is briefly described here. The decorator can be divided into the decorator with parameters and the decorator without parameters. It looks like this. # Syntax is like this @ decorator (dec_opt_args) def func2Bdecorated (func_opt_args ):... # decorator without parameters @ dec1 @ dec2def func ():... # This function declaration is equivalent to func = dec1 (dec2 (func) # decorator with parameters @ dec (some_args) def func ():... # This function declaration is equivalent to func = dec (some_args) (func) some details about the decorator without parameters are described here. A simple cache decorator will be implemented to help you understand it. 1. the decorator function itself accepts a function as a parameter for the decorated function func, and returns a decorated function called decorated_func. Because there are no restrictions on the returned functions, the decorator function can even return new functions that are completely irrelevant to func. However, in most cases, decorated_func is an extra processing function for func. Therefore, a decorated_func is generally corresponding to two functions, and a decorator function is used for initialization operations, one is decorated_func, which is used to implement additional processing of the decorated function func. To maintain reference to func, decorated_func is generally used as the internal function of decorator, for example: # decorated_func is generally used as the internal function of decorator # because the internal function can maintain reference to func (see the closure description in (1) >>> def decorator (func ):... print 'init oppration '... def decorated_func ():... return func (2 )... return decorated_func... 2. the decorator function is called only once when the function is declared. It is actually a syntactic sugar. After the function is declared, it is called to generate decorated_func and replace the reference of the func symbol with decorated_func. Then, each time the func function is called, decorated_func is actually called. >>> Def decorator (func ):... def decorated_func ():... func (1 )... return decorated_func... # called at declaration >>> @ decorator... def func (x ):... print x... decorator being called # using the func () function actually uses the decorated_func function >>> func () 1 >>> func. _ name _ 'corated _ func' if you want to ensure that the name of the returned decorated_func function is the same as that of func, add decorated_func.name = func before the decorator function returns decorated_func. name. In addition, the functools module provides the wraps modifier to complete this operation. # @ Wraps (func) is equivalent to # Run # decorated_func before return decorated_func. _ name _ = func. _ name __# func is passed in as the modifier parameter, # decorated_func is passed in as the parameter of the function returned by wraps >>>> def decorator (func ):... @ wraps (func )... def decorated_func ():... func (1 )... return decorated_func... # called at declaration >>> @ decorator... def func (x ):... print x... decorator being called # using the func () function actually uses the decorated_func function >>> func () 1 >>> func. _ name _ 'func' 3. decorator function board The beauty of Partial Variables because of the features of closure (see section (1), the variables declared by decorated_func.func_closure will be referenced by decorated_func.closure, so after the decorator method is called, the local variables of the decorator method are not recycled. Therefore, you can use the local variables of the decorator method as counters, cache, and so on. It is worth noting that if you want to change the value of a variable, the variable must be a mutable object, so even a counter should also be implemented using a list. The declare handler function calls the decorator function once, so the counters of different functions do not conflict with each other, for example :#! /Usr/bin/env python # filename decorator. pydef decorator (func): # note that the variable object a = [0] def decorated_func (* args, ** keyargs): func (* args, ** keyargs) is used here) # Because the closure is a shortest copy, if it is an immutable object, the symbols will be cleared after each call, cause error a [0] + = 1 print "% s have bing called % d times" % (func. _ name __, a [0]) return decorated_func @ decoratordef func (x): print x @ decoratordef theOtherFunc (x ): print x >>> from decorator import func >>> from decorator import theO TherFunc >>> func (0) 0 func have bing called 1 times >>> func (0) 0 func have bing called 2 times >>> func (0) 0 func have bing called 3 times >>> theOtherFunc (0) 0 theOtherFunc have bing called 1 times >>> theOtherFunc (1) 1 theOtherFunc have bing called 2 times> theOtherFunc (2) 2 theOtherFunc have bing called 3 times4. simple result cache decorator # coding = UTF-8 #! /Usr/bin/env python # filename decorator. pyimport timefrom functools import wrapsdef decorator (func): "cache for function result, which is immutable with fixed arguments" print "initial cache for % s" % func. _ name _ cache ={}@ wraps (func) def decorated_func (* args, ** kwargs): # The key must be a hash object. # It is not rigorous here, an error occurs if the kwargs value cannot be hashed. # For simplicity, no special processing key = (args, tuple (kwargs. items () result = None # determine whether the cache if key in c exists Ache: (result, updateTime) = cache [key] # The expiration time is fixed to 10 seconds if time. time ()-updateTime <10: print "cache hit for", key else: print "cache expired for", key result = None else: print "no cache ", key # if it expires, or there is no cache call method if result is None: result = func (* args, ** kwargs) cache [key] = (result, time. time () return result return decorated_func @ decoratordef func (x): if x <= 1: return 1 return x + func (x-1) >>> From decorator import funcinitial cache for func >>> func (5) no cache for (5,), () no cache for (4 ,),()) no cache for (3,), () no cache for (2,), () no cache for (1 ,),()) 15 >>> func (5) cache hit for (5,), () 15 >>> func (1) cache expired for (1 ,),()) 1 >>> func (2) cache expired for (2,), () cache hit for (1 ,),()) 3. After familiarizing yourself with the use of the decorator without parameters, it is much easier to understand the decorator with parameters. The parameter-based decorators are mainly used to pass some settings, or to select different decorators. We already know that the decorator without parameters calls decorator and returns decorated_func. The decorator with parameters returns the decorator method. After being processed by the decorator method, the decorated_func is returned. Therefore, a modifier with parameters generally consists of three methods. First, call settings_func to accept the parameters, select the decorator method, and then call the returned decorator method to generate decorated_func to process the func. With settings_func, We can customize the decorator. For example, in the cache method previously implemented, the expiration time is fixed to 10 seconds. With settings_func, We can customize the expiration time and determine whether to debug the output. 1. Add configuration parameters for the cache decorator. Here, configure the expiration time and debug the output. # Coding = UTF-8 #! /Usr/bin/env python # filename decorator. pyimport timefrom functools import wrapsdef cache (expirationTime, debug = False): def decorator (func): if debug: print "initial cache for % s" % func. _ name _ cache ={}@ wraps (func) def decorated_func (* args, ** kwargs): # The key must be a hash object. # It is not rigorous here, an error occurs if the kwargs value cannot be hashed. # For simplicity, no special processing key = (args, tuple (kwargs. items () result = None if key in cache: (result, updateTime) = Cache [key] if time. time ()-updateTime <expirationTime: print "cache hit for", key else: if debug: print "cache expired for", key result = None elif debug: print "no cache for", key if result is None: result = func (* args, ** kwargs) cache [key] = (result, time. time () return result return decorated_func return decorator @ cache (10) def func (x): if x <= 1: return 1 return x + func (x-1) besides cache hit, All other messages are disabled by debug = False. >>> Func (5) 15 >>> func (1) cache hit for (1,), () 1 >>> func (2) cache hit for (2,), () 3> func (3) cache hit for (2 ,),()) 6. The decorated functions share variables. In the above example, the variable (counter, cache) of the decorator is declared in the method of the decorator, therefore, these variables in different methods are not universal. You can use class attributes or global variables to make different method variables (such as shared cache) decorated by the same modifier universal. Lambda expressions are actually anonymous functions, similar to javascript Functions ([arg1, [arg2 [...]) {...}. In python, lambda expressions return function instances. In the syntax, lambda follows the parameter, and the colon follows the returned result. >>> Bar = lambda x, y: x + y >>>> type (bar) <type 'function' >>> bar (1, 2) 3 at the same time, lambda expressions also have closure (closure) features: >>> def foo ():... x = 5... y = 5... bar = lambda: x + y... return bar...> foo () 10 in short, lambda expressions all have the features of functions. Like assigning a default value to a parameter, lambda internal variables are not subject to external influences, and all of them act exactly like functions. # Default parameter >>> y = 2 >>> bar = lambda x, y = y: x + y >>> bar (3) 5 # variables defined by lambda are not affected externally >>> y = 5 >>> bar (3) 5 >>>

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.