Yesterday's review
Closure function
1. Definition : Functions defined inside functions , And use the name in the local namespace of the external function
2. One of the methods of parameter transmission : Add something to the same level, and then wrap it with a function to indent
3. From the direction of return value, we study the value of using local namespace from the global
4. In practical application, local namespace sets local namespace , The original local space is closed immediately after the execution of the function code body , But in the case of closure function, it will be different , It closes only when the internal local namespace ends
Decorator
1. The essence : Without changing the original calling method and internal code of the installed function, add new functions to the installed function
2. principle : Closed to modification , For extension development
Decorator important derivation process
1. Count the running time of a function
2. The code that counts the running time of a function is encapsulated into a function
3. Directly repacking into a function will change the calling method
4. Try to pass parameters with closure function
5. Replace the function of the original function with a duplicate name
6. The parameters of the function
7. Function return value
Decorator template
def outer( The function name of the decorated function ):
def inner(*args, **kwargs):
print(' Perform the operations that can be done before the decorated object ')
res = func(*args, **kwargs)
print(' Perform the operations that can be done after the decorated object ')
return res
return Inner function name
''' For two places *args and **kwargs The role of '''
def index(*args,**kwargs):
pass
def func(*args,**kwargs):
index(*args,**kwargs)
'''
args = ([1,2,3,4],)
kwargs = {'name':'jason','age':18}
index(*([1,2,3,4],),**{'name':'jason','age':18})
index([1,2,3,4],name='jason',age=18)
Switching from one place to another is actually giving func What to wear is equivalent to giving index What to pass on
'''
func([1,2,3,4],name='jason',age=18)
'''
[1,2,3,4], Is the redundant position parameter given args Take a data value , In the form of a tuple
name='jason',age=18, Is the redundant keyword parameter given kwargs, In the form of a dictionary
'''
Decorator grammar sugar
@outer # It's equivalent to this ,index = outer(index)
def index():
pass
Decorator repair technology
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
Today's content
Homework explanation
1. Write a user authentication decorator
The basic requirements
The identity must be verified before executing each function eg: jason 123
High practice ( It's a little difficult )
Execute the decorated function As long as the certification is successful once Then the subsequent verification passes
function :register login transfer withdraw
Tips : Global variables Record whether the current user is authenticated
is_login = {'is_login': False, } # If the variable type is changed in the local namespace, there is no need to create a new name
# Write decorators
def lonin_auth(func_name):
def inner(*args, **kwargs):
# Judge the global dictionary is_login Whether the corresponding value True
if is_login.get('is_login'):
# If it is True, It means that the user has logged in , Directly ask him to perform the operation to be performed
res = func_name(*args, **kwargs)
return res
# Verify user identity
username = input(' enter one user name :').strip()
password = input(' Input password :').strip()
if username == 'jason' and password == '123':
res = func_name(*args, **kwargs)
# After successful login , Perform what the user wants
is_login['is_login'] = True # Records after user login
return res
else:
print(' Insufficient user name permission ')
return inner
@lonin_auth
def register():
print(' Registration function ')
@lonin_auth
def login():
print(' Login function ')
@lonin_auth
def transfer():
print(' Transfer function ')
@lonin_auth
def withdraw():
print(' Embody function ')
register()
login()
transfer()
withdraw()
Multi layer decorator
def outter1(func1): # func1 be equal to wrapper2
print(' To load the outter1')
def wrapper1(*args, **kwargs):
print(' Yes wrapper1')
res1 = func1(*args, **kwargs)
return res1
return wrapper1
def outter2(func2): # func2 be equal to wrapper3
print(' To load the outter2')
def wrapper2(*args, **kwargs):
print(' Yes wrapper2')
res2 = func2(*args, **kwargs)
return res2
return wrapper2
def outter3(func3): # func3 Equal to real index function
print(' To load the outter3')
def wrapper3(*args, **kwargs):
print(' Yes wrapper3')
res3 = func3(*args, **kwargs)
return res3
return wrapper3
@outter1 # index = outter1(wrapper2)
@outter2 # wrapper2 = outter2(wrapper3)
@outter3 # rapper3 = outter3( It's true index Function name )
def index():
print('from index')
index()
'''
The function of grammar sugar :
1. It will automatically pass the following function as a parameter to @ Function name after symbol ( Bracketed call )
2. If there is a syntax sugar above the syntax sugar, its return value is not the function name , It depends on the return value after he calls the function
3.wrapper3 = outter3( It's true index Function name ) Medium wrapper3 Is a function name , Then there is a grammar sugar on it , And then it triggers 1 Conditions
....
4. Last use index To receive
result
To load the outter3
To load the outter2
To load the outter1
Yes wrapper1
Yes wrapper2
Yes wrapper3
from index
'''
There are ornaments for reference
1. Add parameters in
2. stay inner Add parameters to
3. The right way of thinking
def outer(condition,type_user):
def login_auth(func_name): # No other formal parameters can be filled here
def inner(*args, **kwargs): # You can no longer fill in the parameters required by non decorated objects
username = input('username>>>:').strip()
password = input('password>>>:').strip()
# Different codes should be executed according to the needs of users
if type_user =='jason':print('VIP')
if condition == ' list ':
print(' Use lists as data sources ')
elif condition == ' Dictionaries ':
print(' Use dictionaries as data sources ')
elif condition == ' file ':
print(' Use files as data sources ')
else:
print(' At present, there are only the above ways ')
return inner
return login_auth
@outer(' file ','jason') # Parenthesized function name execution priority @login_auth
def index():
print('from index')
index()
'''
Illustrate with examples
Multiple data sources can be switched inside the decorator
1. Originally, the decorator was executed step by step
2. Now, after obtaining the user name, there are many situations that are no longer directly executed downward , The implication is that the branch situation needs to be used somewhere
3. if condition == ' list ':
print(' Use lists as data sources ')
elif condition == ' Dictionaries ':
print(' Use dictionaries as data sources ')
elif condition == ' file ':
print(' Use files as data sources ')
else:
print(' At present, there are only the above ways ')
This is the time condition Is an unfixed value , It can be a list 、 Dictionary or file , And this value is from us , Then there are two ways to transfer values in a function , At this time, it depends on which kind of value transfer
4. Add a layer of functions on the outside
summary : If we write another decorator , Its internal needs to pass in additional data to control the branch of the code , In this case, you can set another function on the original basis , And you can pass in multiple values , There is no need to nest functions
'''
Recursive function
1. Introduction to recursive functions
# Call directly : Call yourself
def index():
print('from index')
index()
index()
# Indirect invocation : The two functions call each other directly
def index():
print('from index')
func()
def func():
print('from func')
index()
'''
stay python There is a limit to how many times you can call yourself in , The official limit is 1000 Sometimes there may be a little deviation (997 998...)
'''
import sys
print(sys.getrecursionlimit()) # 1000 Get the maximum number of recursion
sys.setrecursionlimit(2000) # The maximum number of times can be modified
print(sys.getrecursionlimit())
2. Application scenarios of recursive functions
Recurrence : Look for the answer layer by layer
to flash back : Deduce the final answer according to the known conditions
Conditions : Each call is closer to the answer , It's simpler every time , Finally, there must be an end condition
Example description :
l1 = [1, [2, [3, [4, [5, [6, [7, [8, [9, [10, ]]]]]]]]]]
# Cycle through all the numbers in the list
'''
The analysis process :
1.for loop l1 All the data values in it
2. Judge whether the current data value is a number If so, print
3. If not, continue for All data values in the loop
4. Judge whether the current data value is a number If so, print
5. If not, continue for All data values in the loop
6. Judge whether the current data value is a number If so, print
....
thus it can be seen , There is always a piece of code that repeats
'''
def get_num(l1):
for i in l1:
if isinstance(i,int):
print(i)
else:
get_num(i)
get_num(l1)
The dichotomy of algorithms
1. What is algorithm ?
Algorithm is the way to solve the problem , The algorithm is always improving , But there are few perfect algorithms .
2. Dichotomy
It is the simplest algorithm in the algorithm , It is mainly used in ordered sequences , The principle is to halve the original sequence every time you search , An algorithm that gradually reduces the search range
Take the median every time , If it is high, continue to take down the median value of the half , If it is low, take the median value of the upper half , And so on , Finally, find the correct guess .
The defects that exist : If the number searched is at the beginning or end Then dichotomy is less efficient , Only ordered sequences can be found .
Example show :
l1 = [2, 4, 6, 8, 10, 15, 18, 23, 34, 56, 78, 90, 101, 120]
def get_num(l1, target_num):
# Add the end condition of recursive function
if len(l1) == 0:
print(' Can't find ')
return
# 1. Get the middle number , Divide the total length 2, It's the value in the middle
middle_index = len(l1) // 2
middle_value = l1[middle_index]
# 2. Judge whether the intermediate value obtained is smaller than the target number we are looking for , And then discuss the situation , utilize if..elif
if target_num > middle_value:
# 3. If the objective function is greater than the median , Explain that the objective function is on the right , Since it is a freshman, it means that if it is larger than itself, it can be narrowed down a little
right_l1 = l1[middle_index + 1:]
# 3. The same operation is carried out on the right , Find the intermediate value and compare
# After analysis, we know that Recursive functions should be used
print(right_l1)
get_num(right_l1, target_num)
elif target_num < middle_value:
# 4. It indicates that the number to be searched is on the left half of the dataset How to intercept the left half
left_l1 = l1[:middle_index] # The left side doesn't need -1, The index is regardless of the end
# 4. The same operation is carried out on the left , Find the intermediate value and compare
# After analysis, we know that Recursive functions should be used
print(left_l1)
get_num(left_l1, target_num)
else:
print(target_num)
get_num(l1, 18)