Error message here!

Hide Error message here!

忘记密码?

Error message here!

请输入正确邮箱

Hide Error message here!

密码丢失?请输入您的电子邮件地址。您将收到一个重设密码链接。

Error message here!

返回登录

Close

Novice tester who just changed profession for one year: learning python programming experience and sharing

jinjiangongzuoshi 2021-04-21 11:08:30 阅读数:3 评论数:0 点赞数:0 收藏数:0

One 、 Let's start with two sentences

As a novice tester who has just been in a zero base industry for one year , I know that I am far behind in technical experience , It's hard to avoid being eager for success , This also leads to their own in learning new knowledge , At the beginning, when I finished my study, I had a plan , After a period of time, I forgot all about it , Cause me to keep going back to review , It still doesn't get to the point , It is difficult to use flexibly in practice .

I believe many of my classmates are hesitating like me , Now the teacher has given me an opportunity to share my experience with you , I also happened to review some time ago about Python Decorator In terms of understanding , If there is something wrong , I hope you all , Colleague , The teacher pointed out in time that .

Two 、 Decorator must know the foundation

In fact, many knowledge points are not firmly grasped , It is because the most basic knowledge is not fully understood that leads to . This is also my evaluation of myself when I study decorators , So let's talk about the basic knowledge of learning decorators first .

1、 Formal parameter and actual parameter

The parameters of the function are divided into Formal parameters and The actual parameter , Formal parameter and actual parameter for short .

  • Shape parameter When defining a function , Parameters declared in parentheses . A formal parameter is essentially a variable , It is used to receive the value from outside
  • Actual parameters When the function is called , The value passed in parentheses , Values can be constants , Variable , An expression or a combination of the three

Specific use is divided into location parameters , Keyword parameters and default parameters

def info(name,age,sex='male')
print(f'name:{name} age:{age} sex:{sex}')
info(name='jack',18)

In the above example , Call the function with key=value In the form of keyword parameters , When defining a function name,age For position parameters ,sex Is the default parameter .

Be careful

  • When you call a function , Arguments can be mixed by location or keyword , But you have to make sure that the keyword parameter comes after the positional parameter , And you can't assign a parameter repeatedly
  • The value of the default parameter should normally be set to immutable type

2、 Variable length parameter *args and **kwargs

The variable length of a parameter means that when a function is called , The number of arguments may not be fixed , And in the call phase , Arguments are in two forms: by location or by keyword , So there are two solutions to deal with .

2.1 Variable length positional parameters

​ If you add before the last parameter name * Number , So when you call a function , Overflow location arguments are accepted , Save it as a tuple and assign it to the parameter .

def func(x,y,z=1,*args):
print(x,y,z,args)
func(1,2,3,4,5,6,7)
>>1 2 3 (4,5,6,7)
# What works here is * Number , The overflow position parameter is assigned to the variable after it , namely args=(4,5,6,7)

2.2 Variable length keyword parameters

​ If you add before the last parameter name ** Number , So when you call a function , Overflow keyword parameter , It will be saved in the form of a dictionary and assigned to a formal parameter .

def func(x,**kwargs):
print(x)
print(kwargs)
func(x=1,y=2,z=3)
>>1
>>{'y':2,'z':3}
# Same as above, this is equivalent to the overflow keyword argument one ,y,z All be ** Receive a value assigned to in the form of a dictionary kwargs, namely kwargs={'y':2,'z':3}

2.3 Use a combination of

Variable parameters *args And keyword parameters kwargs Usually used in combination , If the formal parameters of a function are of the above two types , So it means that the function can receive any form of , Parameters of any length .

def wrapper(*args,**kwargs):
pass

Inside the function, you can pass the received arguments to another function , This is very useful in deriving the decorators later .

def func(x,y,z):
print(x,y,z)
def wrapper(*args,**kwargs):
func(*args,**kwargs)
wrapper(1,y=2,z=3)
>>1 2 3

analysis

This is for wrapper Reference time , It follows the function func Parameter rules of , First step , Positional arguments 1 Accepted , Save it as a tuple and assign it to args, namely args=(1,), Key parameters y=2,z=3 By ** Receive an assignment to in the form of a dictionary kwargs, namely kwargs={'y':2,'z':3}; The second step , perform func(args,kwargs), namely func((1,),{'y':2,'z':3}), Equate to func(1,y=2,z=3).

3、 Function objects and closures

Function objects are functions that can be treated as " data " To deal with it , It can be divided into four aspects

3.1 Functions can be referenced

def add(x,y):
return x+y
func = add
func(1,2)
>>3

3.2 Functions can be elements of a container type

dic = {'add':add}
>>dic
>>{'add': <function add at 0x100661e18>}
>>dic['add'](1,2)
>>3

3.3 Function can be passed into another function as an argument

def foo(x,y,func):
return fun(x,y)
>>foo(1,2,add)
>>3

3.4 The return value of a function can be a function

def bdd():
return add
func=bdd()
func(1,2)
>>3

3.5 Closure functions have two key points

  • " close ": When a function is valued, it is defined within another function, that is, an embedded function .

  • " package ": It means that the function contains a reference to the outer function acting on the variable .

    def f1():
    x = 1
    def f2():
    print(x)
    f2()
    # here f2 It's an embedded function , by ‘ close ’,f2 There are outer variables x References to , by ‘ package ’
    # But we don't want to call... Internally f2 What about functions
    # This is the reference to the function object , It can be solved as a return object , namely :
    def f1():
    x = 1
    def f2():
    print(x)
    return f2 # Be careful not to bracket , The other is to return f2 The results of the implementation of , What we need is his memory address for external call at any time
    f = f1() # At the moment, variables f What I've received is f2 Memory address of
    

summary :

Closure function provides a new way to transfer parameters to function body , To give f2 Pass value , Gave him a value in his peer scope ,f2 Indent on the whole , I'll nest him another function f1 wrap up . here f1 From the original overall situation to the local , So that we can still call it globally , adopt return The function object returns to the global .

3、 ... and 、 What is a decorator

So much has been said , Maybe you're a little confused, why don't you introduce decorators . Don't worry , This is also a mistake we often make in our study , Eager for success is not conducive to the absorption of knowledge, digestion and understanding . In fact, imperceptibly , We've already mentioned most of the basic knowledge of decorators , It's just that it hasn't been sorted out yet . Next, we will deduce its origin step by step .

Definition : Define a function ( class ), This function is specifically used for other functions ( object ) Add extra features .

The decorator is essentially a python A function or class , It allows other functions or classes to add extra functionality without any code changes , The return value of the decorator is also a function / Class object . It is often used in scenarios with faceted requirements , such as : Inserting log , Performance testing , Transaction processing , cache , Permission check and other scenarios .

Four 、 Why decorators

When we add new functionality to an object , They always adhere to the principle of openness and closeness .

  • to open up : Open to expanding functions
  • closed : It means that modifying the source code is closed

That is to say, add new functions for the decorated object without modifying the source code and calling method of the decorated object . We have decorators , We can extract a lot of the same code that has nothing to do with the function itself and reuse it again .

5、 ... and 、 The derivation of decorator

Put forward requirements : by index Function adds the function of calculating the running time of code , It must be open and closed .

import time
def index(x,y):
time.sleep(2)
print(f' come from index Of {x} and {y}')

1、 Scheme 1

def index(x, y):
start = time.time()
time.sleep(2)
print(f" come from index Of {x} and {y}")
stop = time.time()
print(stop-start)

result : Although the function has been realized , But it broke the open and closed principle , Changed the source code , Unqualified , Failure .

2、 Option two

start = time.time()
index(1, 2)
stop = time.time()
print(stop-start)

result : Although the above code did not modify the source code , Also realized the function , But add these three lines of code to each use , Too redundant , Failure .

3、 Option three

''' Optimize on the basis of scheme 2 , In order to solve the problem of code redundancy , Let's write it as a function '''
def wrapper():
start = time.time()
index(1, 2)
stop = time.time()
print(stop-start)
wrapper()

result : We don't have to add three lines at a time , Just call wrapper Function , But reusability is still not enough , It can be in progress Optimize .

4、 Option four

Optimize : solve index It's a dead question that you've written about

# At this point, the knowledge of function parameters is used
def wrapper(a, b):
start = time.time()
index(a, b)
stop = time.time()
print(stop-start)
wrapper(1,2)
# But maybe in the follow-up needs index The number of parameters will change
# At this point, variable length parameters can help a lot
def wrapper(*args, **kwargs):
start = time.time()
index(*args, **kwargs)
stop = time.time()
print(stop-start)
''' At this time, you don't have to worry about passing parameters to him ,wrapper Any parameters received will be handed to index function '''

result : A series of optimizations , We found that although the problem of parameter transfer has been solved , But at this point index Functions are dead, too , It can't be the only one that needs this function in the future , Reusability is not enough , So we can continue Optimize .

5、 Option five

Optimize :index Write dead questions

''' We know that once a variable is dead , So let's replace it with a variable , But in wrapper Function ,index When it's written as a variable , It can't be passed to him through formal parameters , At this time, the closure function will be very powerful , It provides a way to pass parameters to a function '''
def outter(func):
#func = index # Live writing
def wrapper(*args, **kwargs):
start = time.time()
func(*args, **kwargs)
stop = time.time()
print(stop-start)
return wrapper
f = outter(index)
''' The return is wrapper The memory address of is assigned to f, Adding parentheses is calling wrapper, Its function is to calculate the function object passed into it index Execution time statistics of '''
# In order not to change the call mode , Optimizing
# You can put f = outter(index), Why can't it be assigned to index Well
# Last :index = outter(index) namely wrapper Memory address of
index() # At this point, for the caller of the function , He hasn't changed , It's been changed a long time ago

6、 Option five

Optimize : It seems that it has been optimized almost , In fact, there are loopholes , Primitive function index There is no return value , At this point, call the replace index after , On return wrapper Memory address of , It doesn't return a value ,index() The return is None, It's not perfect . At this time, we need to use the function object reference mentioned above as the return value , The problem is solved .

def outter(func):
#func = index # Live writing
def wrapper(*args, **kwargs):
start = time.time()
res = func(*args, **kwargs)
stop = time.time()
print(stop-start)
return res
return wrapper
''' We put func The return value of the function passes through return, Coming back out , When we run index() when , It's actually calling wrapper, Now it has a return value , That is to say func The return value of , This is the perfect time '''

6、 Final plan ( recommend )

def outter(func):
def wrapper(*args, **kwargs):
res = func(*args, **kwargs)
return res
return wrapper

This is the simplest template for a parameterless decorator , We want to give someone, that is func Function to add new functions directly in wrapper Write code inside the function .

About the parametric decorator , Because of space limitation, I will not explain it here . Having a parameter means that we need a parameter inside our function , There are only two ways , One is passed in directly through formal parameters , The other is to wrap it directly through the closure function , It must be more reasonable to use closure function here .

6、 ... and 、 speech

accidentally , Because a teacher's homework task , Completed my first knowledge summary . It was a bit of a panic at first , But then came the surprise , Even though I'm worried that it's not good enough , But I want to give myself an account , A good start . The continuous sharing and summary of knowledge can promote our continuous learning progress .

After this little sharing , Back to the beginning , What I want to say is to learn some advanced knowledge , When we feel fuzzy , Let's go back to the essence , Decompose him from the most basic principles , Step by step deduction , Often can give us a kind of enlightenment , Unexpected gains . Finally, I hope to work with you through this study , Improve yourself , Complete your original intention .

At the beginning of xinchou Struggle is more than

​ -- Lipan

Copyright statement
In this paper,the author:[jinjiangongzuoshi],Reprint please bring the original link, thank you

编程之旅,人生之路,不止于编程,还有诗和远方。
阅代码原理,看框架知识,学企业实践;
赏诗词,读日记,踏人生之路,观世界之行;