A Python beginner's monologue: Python decorators white eyes

This is a micro letter to see an article, just learning Python partner soon, I seriously looked at is indeed a very real partner just started learning Python! I put this article to get it, I hope more new to Python partners can learn something, be enlightened!

A Python beginner's monologue: Python decorators white eyes

 

It reads as follows:

hello, Hello everybody, first of all tell us about, I'm not a program ape in the true sense. In recent Python learning this language, want to have a place to record climb pit. Standing R & D despise the bottom of the chain, but also want to reduce duplication of work by some means to improve efficiency. Python that this language can be a good help me to solve these problems. Today will take you to meet the eyes of the white "decorator."

White study, the concept is a must * 3 To learn and understand! ! What is the decorator, decorator and what you can do about it! ?

First, the concept of decoration is an application of closure (closure will be mentioned later, this is not explained), the need to satisfy my rule:

1. without changing the internal code of the original performance function, and change the method call to add new features to the original function

2. Follow the principle of open closed, open closed principle is what it?

a. Implemented functions can be added or extended with new functionality (principle of openness)

b. well modify the internal function code is implemented (closed principle)

Secondly role, login authentication, after a long statistics do before performing the function of preparation, execution function cleaning function, in short, you can think of extension most of them can achieve function is running, but in the case of the original function code without modification It can be elegant finish!

Look at with practice decorator, personal experience of the problem! Because the work which needs to obtain a regular interface data, so a simple method for obtaining a package of data, as follows:

Import Requests 
Import Re
DEF send_request_by (Method, URL, Data):
"" "
The request interface to obtain data
mode initiation request:: param Method
: param URL: Request Address
: param data: Request Data
: return:
" ""
IF Re. match ( "the POST", Method, the flags = re.IGNORECASE):
Response = requests.post (URL, Data = Data)
IF re.match ( "the GET", Method, the flags = re.IGNORECASE):
Response = requests.get (URL, Data = Data)
return Response

Now it seems that their needs have been met, but every request found or an error! The final analysis found that the packet capture tool, interface calls when the client more of a "sign" field, which is how come it? After analysis "sign" is in encrypted come, in order to solve this problem for a transformation code, the code is as follows:

def send_request_by(method, url, data):
md5_pwd = MD5Password()
data['sign'] = md5_pwd(data)
if re.match("POST", method, flags=re.IGNORECASE):
response = requests.post(url, data=data)
if re.match("GET", method, flags=re.IGNORECASE):
response = requests.get(url, data=data)
return response

 

This seems to solve the problem, but in fact there is no flexibility to solve the problem. How, if one day they do not require encryption signature is not have to add two new lines of code to get rid of? Then how can you not modify the original function can add the encryption functionality yet. After a big brother for advice and found that can be achieved by a decorator, once the code was modified code is as follows:

def sign_md5(func):
def wrapper(*args, **kwargs):
if not kwargs.get('data'):
raise KeyError("not found Key 'data'")
if kwargs.get('data') is None:
raise ValueError(f'{kwargs.get("data")} of value is None')
# 首字母排序
sort_data = json.loads(json.dumps(kwargs.get('data'), sort_keys=True))
# 私有加密规则,生成签名
md5_pwd = MD5Password()
sign = md5_pwd(sort_data)
sort_data['sig'] = sign
kwargs['data'] = sort_data
ret = func(*args, **kwargs)
return ret
return wrapper
@sign_md5 # send_request_by = sign_md5(send_request_by)
def send_request_by(method, url, data):
# Md5_pwd MD5Password = ()
# data['sign'] = md5_pwd(data)
if re.match("POST", method, flags=re.IGNORECASE):
response = requests.post(url, data=data)
if re.match("GET", method, flags=re.IGNORECASE):
response = requests.get(url, data=data)
return response

After testing found that a very flexible solution to the problem, do not require encryption when commenting out @ sign_md5 can! Then the @ sign_md5 in the end to do what?

Its essence is in the case of not using the "@" magic is sign_md5 (send_request_by) (method, ulr, data), and when using the "@" magic decorated, this line is the parser code execution will be decorated send_request_by passed as an argument to sign_md5, i.e. send_request_by has passed as the function of the variable to sign_md (func) func parameter, and returns the wrapper function, the next call send_request_by (method, url, data) function, in fact, At this point send_request_by not the original def send_request_by (method, url, data) in send_request_by, but point to the wrapper (* args, ** kwargs) function. The wrapper function takes any arguments, so when performing send_request_by (method, url, data) function, in fact, pass the method, url, data warpper parameter to the function, and internal code execution wrapper, while the interior of the wrapper function func is our incoming after send_request_by function, and can be understood as meaning, we passed the parameter wrapper function, the wrapper function in encrypted request parameters passed to the function send_request_by request to complete a request before the encryption process. And the inner wrapper function func (* args, ** kwargs) is directed send_request_by (method, url, data) and is to return ret send_request_by (method, url, data) the result of the function, so it will return ret. This more convoluted, multi stroked a stroke believe that with your intelligence will understand! When you will think, wow! It could be so simple! ! ! And so far, the easiest to complete this without parameters decorator! Leaders will praise you, Xiuer!

Then, after resolving this need and I had new doubts, if not someday develop sorted by the first letter of the field, how can I do! ? ? You are not going to re-write a decorator? ? ? Is there any way that can be controlled within decorator whether to sort it? So also through a variety of brain supplement, but has been modified and a code, the code is as follows:

def sign_sort(sort=True):
def sign_md5(func):
def wrapper(*args, **kwargs):
if not kwargs.get('data'):
raise KeyError("not found Key 'data'")
if kwargs.get('data') is None:
raise ValueError(f'{kwargs.get("data")} of value is None')
# sort 参数控制是否按首字母排序
sort_data = json.dumps(kwargs.get('data'), sort_keys=True) if sort else json.dumps(kwargs.get('data'))
sort_data = json.loads(sort_data)
# 私有加密规则,生成签名
md5_pwd = MD5Password()
sign = md5_pwd(sort_data)
sort_data['sig'] = sign
kwargs['data'] = sort_data
ret = func(*args, **kwargs)
return ret
return wrapper
return sign_md5
@sign_sort(sort=True) # send_request_by = sign_sort(sort=Ture)(send_request_by)
def send_request_by(method, url, data):
print(data)
if re.match("POST", method, flags=re.IGNORECASE):
response = requests.post(url, data=data)
elif re.match("GET", method, flags=re.IGNORECASE):
response = requests.get(url, data=data)
return respons

That this time what had been done to optimize it? But it is still the basis of learning without reference decorator on learning a bit parameters decorator. It is still the same recipe. Our analysis together,

First look sign_sort (sort = True), sign_sort essentially a function of receiving a parameter and returns sign_md5 function.

When the code is executed "@" where the row, the same will be decorated send_request_by passed as an argument to a function sign_sort (sort = True) the result of calling a function (i.e. sign_md5).

That send_request_by function is as a variable (function can also be variable) sign_md5 passed to the function func in the parameter and returns a wrapper function.

Call send_request_by (method, url, data) in the back function, the same is no longer at this time send_request_by def send_request_by (method, url, data) in the function send_request_by, but wrapper (* args, ** kwargs) function.

wrapper function receives any parameter, so when performing send_request_by (method, url, data), would method, url, data is passed to the wrapper function, executing code within the wrapper function, and the inside of the wrapper func (* args, ** kwargs ) or point send_request_by, can be understood as to pass parameters to send_request_by function through the wrapper function, but before being passed on to send_request_by, we can do any operation on the parameters, so before I pass judgment whether the sort parameter to True as a sort of switch , and then the data is encrypted request data operation, the final signature is transmitted with the encrypted request to transmit send_request_by function. Is not it amazing, very simple! ? In fact, decorator and not imagined so difficult to understand, but there is a little convoluted, need to be able to analyze pointers to functions, so you can easily control, "decorator" to make your code more elegant! ! The boss did not have the heart does not give you a raise! ! !

I write to you, one of Python in the "magic" function decorators will almost finished, in fact, can be written in the same class decorator decorator, and broader usage, I have not come into contact with the white of ~ ~ point hoping to get big brother (anger) dialing (hate)!

As in Python "magic" There are many, many, such as the above code, md5_pwd = MD5Password obviously an object, why can the same as calling the function (md5_pwd ()), as well as how to write a class decorator it? These functions are by magic __call__ Python underlying method to achieve! Then the next time the theme is __call__ method, I will tell acquaintance of __call__ methods, and new understanding!

Finally, there are certainly wrong about the place, welcomed the various codes heavyweights to hate me, educate me, correct me! ! Because I really want to learn Python! !

My vision is determined to do a development, test, train engineers! Code write more elegant! (Then girlfriend and take private live ~~~ hhhh) very little real partner, ah, after all, once I had this idea, ha ha ha! When you are new to Python what kind of mood and sentiment of it! You can also leave a message Ha!

Original article: xiaoanzi SOYBEAN melon seed

Guess you like

Origin www.cnblogs.com/cherry-tang/p/11131608.html