Today's content
Introduction to closure function
Closure function : Only when the following two functions are satisfied can it be called a closure function
1. Functions defined inside functions
2. The inner function uses the name in the outer function namespace
username = 'jason'
def func():
def index():
print(username)
'''
problem : function index() Is it a closure function ?
No ,print(username) Inside username It is used in the global namespace
'''
def func():
username = 'jason'
def index():
print(username)
''' This is the closure function '''
'''
Think about how to invoke index?
Thinking process :
def func():
username = 'jason'
def index():
print(username)
return 123
The return is 123
def func():
username = 'jason'
def index():
print(username)
return username
The return is username Bound value jason
def func():
username = 'jason'
def index():
print(username)
return index
res = func()
print(res) # <function func.<locals>.index at 0x0000020793F87790>
The function name is returned , here res It is the memory address bound to the function body code in the memory space , At this time, it is the same as the function name , Then call the function and add () That's it
'''
''' Use the value of local namespace from the global '''
def func():
username = 'jason'
def index():
print(username)
return index
res = func()
res() # jason
''' If so , Or is it not a closure function '''
def func(username):
# username = 'jason'
def index():
print(username)
return index
func('jason')
'''
explain : In the call phase , Formal and actual parameters back to temporary binding , That is, when it is called, it actually happens that Jason Bind to username 了 , So at this time func A name will appear in the local namespace
Therefore, it also conforms to the definition of closure function
'''
Practical application of closure function
def func(username):
# username = 'jason'
def index():
print(username)
return index
func('jason')
'''
When there is a local space in the local space , The original local space is opened when the function body code runs and closed when the function body code ends , Then it will be different in this case at this time
When func() He won't turn it off when running , Because it detects the back index() You also need to use , It will remain open until the local namespace inside is closed
'''
''' The way to pass values to the function body code 1: Through formal parameters '''
def func(XXX):
print(XXX)
''' The way to pass values to the function body code 2: Closure function '''
def index(username):
# username = 'jason' # If you write it like this, it's dead
def func():
print(username)
return func
# res = index() # res Namely func
# res() # Namely func(), Then you can call repeatedly res()
res = index('jason')
res()
res1 = index('kevin')
'''
1. Creation of built-in namespaces
2. Global namespace (index)
3.index('jason'), Parenthesized function names have the highest execution priority , perform index() Function call , take jason Pass to username
4.index() Local namespace creation (username binding jason、func())
5.func Back to the global namespace res in
6. Function name res Bracketed ,res()=func(), call func() function
7.func() Function to find username, There is no , I found it on the upper floor jason
'''
About decorators
1. The essence of ornaments
Without changing the decorated object [ The original call mode ] and [ Internal code ] Add new functions to the decorated object
2. The principle of decorators
Closed to modification Open to expansion
3. Knowledge reserve
import time
print(time.time()) # 1657011706.287414
''' Time stamp ( Number of seconds ): The current distance 1970 year 1 month 1 Japan 0 when 0 branch 0 The number of seconds experienced in seconds '''
time.sleep(4)
'''
Let the program wait for four seconds
The number controls the number of seconds , It's when the program runs in a few seconds
'''
print('123456')
Decorator derivation process
import time
print(time.time()) # 1657011706.287414
''' Time stamp ( Number of seconds ): The current distance 1970 year 1 month 1 Japan 0 when 0 branch 0 The number of seconds experienced in seconds '''
time.sleep(4)
'''
Let the program wait for four seconds
The number controls the number of seconds , It's when the program runs in a few seconds
'''
print('123456')
# Count the running time of the code
# start_time = time.time() # 100
# for i in range(100000):
# print(i)
# end_time = time.time()
# print('for The execution time of the loop is :%s'%(end_time - start_time))
def index():
time.sleep(2)
print('from index')
start_time = time.time() # Calling index Get the timestamp before the function
index() # call index function
end_time = time.time()
print(end_time - start_time)
'''
If you want to call it more than once index()
Then the code before and after it will be called every time
start_time = time.time() # Calling index Get the timestamp before the function
index() # call index function
end_time = time.time()
print(end_time - start_time)
In this way, you will have to write these lines of code every time you call
defects 1:
If there are more than one index It takes time to count , You need to write code repeatedly
Solutions : Encapsulate as a function
'''
def get_time():
start_time = time.time() # Calling index Get the timestamp before the function
index() # call index function
end_time = time.time()
print(' The execution time of the function is :', end_time - start_time)
'''
defects 2:
If there are many different functions that need to count time , Then the above solutions are not perfect
Solutions : Add formal parameters to the function body ( Dynamic transfer parameters )
'''
def home():
time.sleep(3)
print('from home')
def get_time(xxx):
start_time = time.time() #
xxx() # call index function
end_time = time.time()
print(' The execution time of the function is :', end_time - start_time)
get_time(index)
get_time(home)
'''
defects 3:
Functions with different number of formal parameters cannot be compatible with statistics
Solutions :*args,**kwargs, But it cannot be achieved at present
'''
def home():
time.sleep(3)
print('from home')
def get_time(xxx):
start_time = time.time() #
xxx() # call index function
end_time = time.time()
print(' The execution time of the function is :', end_time - start_time)
def func1(a):
time.sleep(1)
print('from func1')
get_time(func1())
'''
defects 4:
Changed the original calling method
Solutions :*args,**kwargs, But it cannot be achieved at present
Using closure functions
'''
def index():
time.sleep(2)
print('from index')
def home():
time.sleep(3)
print('from home')
def outer(xxx):
# xxx = index
def get_time():
start_time = time.time() # Calling index Get the timestamp before the function
xxx()
end_time = time.time()
print(' The execution time of the function is :', end_time - start_time)
return get_time
# res = outer(index)
# print(res) # <function outer.<locals>.get_time at 0x000002570FBD7820>
# res()
# res1 = outer(home)
# print(res1) # <function outer.<locals>.get_time at 0x000002570FBD78B0>
# res1()
'''
1. Define a function outer(), It won't be turned off immediately
2. Then put the function name index Assign a value to outer The formal parameter of the function XXX
3. Define a function get_time(), return get_time, Use variable name res receive get_time
4.res()=get_time(), And then execute index()
'''
index = outer(index)
index()
home = outer(home)
home()
'''
1. Define a function outer(), It won't be turned off immediately
2. Then put the true function name index The function name is assigned to outer Formal parameters in local namespaces XXX
3. Define a function get_time(), return get_time, Use variable name res receive get_time
4. Use a function name ( And Zhengzhen index The function names are consistent ) To receive get_time
5.
'''
Decorators argue about how to be compatible with parameterized and nonparametric functions
import time
""" For the compatibility of parameterized and nonparametric functions """
def outer(xxx):
def get_time(*args, **kwargs):
start_time = time.time()
xxx(*args, **kwargs) # Take out one by one * The value of the data type after the number , Send it once funv('jason')
end_time = time.time()
print(' The execution time of the function is :', end_time - start_time)
return res
return get_time
def home():
time.sleep(2)
print('from home')
return ' perform home The return value after the function '
def index(name):
time.sleep(1)
print('from index')
return ' perform index The return value after the function '
index = outer(index)
res = index('jason')
print(res)
home = outer(home)
home()
def func(a,b,c):
time.sleep(1)
print('from func')
index = outer(index)
index('jason')
home = outer(home)
home()
func = outer(func)
func(1,2,3)
import time
def outer(xxx):
def get_time(*args, **kwargs):
start_time = time.time()
res = xxx(*args, **kwargs) # Take out one by one * The value of the data type after the number , Send it once funv('jason')
end_time = time.time()
print(' The execution time of the function is :', end_time - start_time)
return res
return get_time
def home():
time.sleep(2)
print('from home')
return ' perform home The return value after the function '
def index(name):
time.sleep(1)
print('from index')
return ' perform index The return value after the function '
home = outer(home)
xxx = home()
print(xxx) # None
index = outer(index)
res = index('jason')
print(res)
Decorator fixed template with grammar sugar
'''
1. First, write an outer function
2. Write another function inside
3. If you want to install a decorator for a function , Write the function , then function = Outer function name ( function ),res = function (), Print res
4. function = Outer function name ( function ), Sugar can be used instead of
'''
from functools import wraps
def outer(func_name):
@wraps(func_name) # # It is to make the decorator not easy to be found by others , To truly confuse the false with the true , Will not affect the code , You can write it or not
def inner(*args, **kwargs):
print(' Perform additional operations that can be done before the decorated object ')
res = func_name(*args, **kwargs)
print(' Perform additional operations that can be done after the decorated object ')
return res
return inner
''' How to use it? ??'''
import time
def home():
time.sleep(1)
print('from home')
return 'home Return value '
home = outer(home) # Special usage of decorator
res = home()
print(res)
'''
Perform additional operations that can be done before the decorated object
from home
Perform additional operations that can be done after the decorated object
home Return value
perform home Before the function, you need to add the function of verifying user identity
def outer(func_name):
def inner(*args, **kwargs):
username = input('username:').strip()
password = input('password:').strip()
if username == 'jason' and password == '123':
res = func_name(*args, **kwargs)
return res
else:
print(' Not enough permissions ')
return inner
username:jason
password:123
from home
home Return value
username:zhanran
password:123
Not enough permissions
None
'''
'''
Decorator grammar sugar
If you want to install a decorator for a function , Just add one to the function @outer(=(home = outer(home)))
'''
# import time
# @outer
# def home():
# time.sleep(1)
# print('from home')
# return 'home Return value '
# print(home) # <function outer.<locals>.inner at 0x000002A1578E70D0>
def index():
' I am a index function '
pass
help(index)
'''
Help on function index in module __main__:
index()
I am a index function
ps:help It can prompt the core data of the things in brackets
'''