Those "artifacts" in Python

Source: Internet
Author: User

"Martial arts Supreme, blades Slaughter Dragon, command the world, Mo dare not from, rely on the sky, who and the battle", this is the artifact. However, the python in today's "artifact" is not so powerful, here to say "artifact" is actually the name inside with a "device", as follows:

    1. List Parser
    2. Iterators
    3. Generator
    4. Decorative Device
List Parser

Now it's time to solve the problem: "There is a list of numbers that asks for the odd number in the list multiplied by 2, returns the list after processing is complete (not changing the order of the original list, only to the odd number in the list by 2)", the more traditional approach might be this:

def double_odd_number_list(odd_number_list):    ret_value = []    for number in odd_number_list: if number % 2: ret_value.append(number * 2) else: ret_value.append(number) return ret_value
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

Test data:

if __name__ == ‘__main__‘:    test_odd_number_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 24, 13, 28] print double_odd_number_list(test_odd_number_list)
    • 1
    • 2
    • 3

Test results:

This is easier for beginners to understand, but the code is not streamlined enough to see how the list parser can do the work:

print [(number*2) if number % 2 else number for number in test_odd_number_list]
    • 1
    • 2

Code Description:

    1. For number in test_odd_number_list iteration test_odd_number_list, for each element in Test_odd_number_list, if an odd number (if branch) is placed in the result list * *, otherwise put in number (else branch)

Test_odd_number_list is also defined above, the test results are as follows:

The above may not meet all of your needs, such as the following situation:

Builder expression

The list parser consumes large amounts of memory when the resulting list of data is large, and it saves all of the data in a single pass to the list and returns it, whether on a calculated time or memory consumption, which is unacceptable when the amount of data reaches a certain level. An improved method is to use the generator expression, the only difference between the syntax and list parsing of the generator expression is [] replaced by (). It returns a generator that calculates only one value at a time (deferred calculation), such as:

Iterators

The details of the iterator can be referred to my other blog, "Python's iterator"

Generator

When it comes to generators, you have to talk about a keyword in python. The definition of the generator in Yield,python is: "A function which returns an iterator", which does not differ from normal or with the addition of the yield keyword. The yield keyword's role is to suspend the execution of the function, and the next time all the environment resumes to the suspended state from where it was suspended, it is usually placed in a loop. Let's look at an example of factorial:

There are a few points that need clarification:

    1. There can be multiple yield functions in a generator function, like the example above
    2. The function is executed in the same order as the normal function, which can be understood as yield is a return, but after return the function hangs at that point, and the next time the function is called, the execution proceeds from that point. For example factorial (2), the function will be executed directly to the while loop (because N!=0), the first loop to yield when RET *= I, the result of the calculation is 1, returns 1 and hangs, at this time I=1,ret equals 1, and then one call from the next line of yield execution, I becomes 2, is less than or equal to the incoming n=2, continues the loop (not executed from the function's head), then ret=2 to yield, returns 2 and hangs, and so on
    3. Usually less, the first time I see it in code is ceilometer (OpenStack a subproject)
Decorative Device

Decorators, cosmetic, where the façade is a function, used to decorate functions or methods, in Python we habitually bind to the instance of the call method, Unbound called function, that is, in the class the first argument to self is the method, in the module is the function. There are two types of adorners in Python: adorners with parameters, adorners without parameters

Adorner with no parameters

Let's start with a syntactically relatively simple adorner with no parameters. When we evaluate the performance, we may be accurate to a specific function to take the time to spend, the latest thing the novice think of is to write a script, before and after the call to get the current time, the difference is the function of the time spent executing, the code may be this:

def test(ret_value, sleep_time):    time.sleep(sleep_time)    return ret_valueif __name__ == ‘__main__‘: start = datetime.datetime.utcnow() test((1, 2, 3, 4, 5, 6), 3) end = datetime.datetime.utcnow() print (end - start).total_seconds()
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

The code is easy to understand, but what if there are a number of functions that need to be tested? Is it necessary to repeat the writing many times:

start = datetime.datetime.utcnow()end = datetime.datetime.utcnow()print (end - start).total_seconds()
    • 1
    • 2
    • 3

If you want to be a good programmer, then do your best to avoid repeating things, let you write each line of code to maximize the value of the following to see an example using adorners:

Import datetimeImport time__author__ =' Administrator 'DefTime_counter(func):DefDoc_func (*args, **kwargs): start = Datetime.datetime.utcnow () ret = func (*args, **kwargs) end = Datetim E.datetime.utcnow () return ret, start, end, (End-start). Total_seconds () return doc_func @time_counter def test (Ret_value, sleep_time): Time.sleep ( Sleep_time) return ret_valueif __name__ = =  __main__ ': print Test (1, 2, 3, 4,  5, 6), 3)        
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21st
    • 22
    • 23

Time_counter is an adorner, which differs from normal functions in that:

    1. parameter is a function object (time_counter parameter func)
    2. A new function (Doc_func in time_counter) is defined in the function, and the parameter list of the function (Doc_func in time_counter) is consistent with the argument list of the function object in step 1th (the Time_counter parameter, func)
    3. The function finally returns the newly defined function object (Doc_func in Time_counter)
    4. @time_counter def func(*args, **kwargs):Equivalent to func = time_counter(func)
      Use the adorner on any function that needs to calculate the execution time, as follows:
@time_counterdef test(ret_value, sleep_time): time.sleep(sleep_time) return ret_value
    • 1
    • 2
    • 3
    • 4

When the test function is executed, the test function object is first passed as a parameter to the Time_counter adorner, which is the formal parameter func, followed by all operations in the defined Doc_func, where Func is called (ret = func (*args, * * Kwargs)) calls the test function, and the following is the result of the execution of the above code:

Adorner with parameters

The adorner above does not need to pass any parameters when it is used, but sometimes this is not enough to meet our needs, assuming that we have a test case in a set of testing frameworks, there may be multiple levels of test cases, fully tested we need to perform all levels of test cases, if a release is only modified one of the small pieces of functionality, For unmodified parts, we only need to test the basic functionality, such as a level greater than or equal to 2. Let's take a look at the decorator simulation with parameters to implement this function:

Import datetimeImport time__author__ =' Administrator 'DefSkip_unit_test(func):Print' Skip function:%s '% func.func_nameDefUnit_test_filter(level):DefNew_decorator(func):DefFinal_func(*args, **kwargs):If level >=2:start = Datetime.datetime.utcnow () ret = func (*args, **kwargs) end = Datetime.datetime.utcnow ()Print ret, start, end, (End-start). Total_seconds ()Else:skip_unit_test (func)Return Final_funcReturn New_decorator@unit_test_filter (0)DefTest_level_zero(Ret_value, Sleep_time): Time.sleep (Sleep_time)Return Ret_value@unit_test_filter (1)DefTest_level_one(Ret_value, Sleep_time): Time.sleep (Sleep_time)Return Ret_value@unit_test_filter (2)DefTest_level_two(Ret_value, Sleep_time): Time.sleep (Sleep_time)Return Ret_value@unit_test_filter (3)DefTest_level_three(Ret_value, Sleep_time): Time.sleep (Sleep_time)Return Ret_valueif __name__ = =' __main__ ': Test_level_zero ((1,2,3, 4, 5,  6), 3) Test_level_one ((1, 2, 3, 4, 5, 6), Span class= "Hljs-number" >3) test_level_two ((1, 2, 3, 4, 5, 6), 3) Test_level_three ((1, 2, 3, 4, 5,  6), 3)            
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21st
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54

Looks more complicated, let's summarize the features with parametric adorners:

      1. is a function that has one or more parameters that returns a defined child function object
      2. The function body defines a child function, the parameter of the child function is the function object, with the Func in the "No parameter adorner", the child function still returns the defined grandchild function object
      3. A grandchild function is defined in the child function, and the parameter list of the Sun Tzu function is consistent with the parameter list of the child function parameter func and is processed in it, and will eventually be called to the decorated function (a single decorated function may not be called)
      4. When using, you need to follow the parameter list of the adorner function to pass the parameters, as in the example: @unit_test_filter(0)
        The results of the above example are attached below:

Those "artifacts" in Python

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.