SoFunction
Updated on 2024-11-13

An introduction to python decorator exploration and parameter collection

First on the original article:

Now, suppose we want to enhance the functionality of the now() function, for example, by automatically printing a log before and after the function call, but we don't want to change the definition of the now() function. This way of dynamically adding functionality while the code is running is known as a "decorator".

Essentially, a decorator is a higher-order function that returns a function.

Decorator is essentially a higher-order function?

Unbelievingly, I tried it...

def g():
 print("This is G.")
 return "G"

@g
def f():
 print("This is F.")
 return 1
'''
--------------------------------------------
line 5, in <module>
 @g
TypeError: g() takes 0 positional arguments but 1 was given
>>>
'''

The results of the run are in the comments

Awkward... ..g is forced to take a parameter, which is supposed to be the object g "modifies."

Modified to continue .....

def g(f):
 print("This is G.")
 return "G"

@g
def f():
 print("This is F.")
 return 1
'''
--------------------------------------------
Here it is.G
>>> f()
Traceback (most recent call last):
 File "<pyshell#0>", line 1, in <module>
 f()
TypeError: 'str' object is not callable
'''

The str object cannot be called,,, there is only one str here, the return value of g

Just to be sure, I changed the "G" to 2.

prove

TypeError: 'int' object is not callable

OK, the general idea is that the decorator is first "stuffed" with a parameter, and then the return value has to be called once, but it seems that only functions can be called,, so, in order not to report an error, the decorator must return a function, and the decorator must be a higher-order function. ......

I beg to differ.( ̄へ ̄),It's just a function.,gThe argument to the function,,,lit. dirty operation on the brain (idiom); fig. a sensationalist approaching

def g(f):
 print("This is G.")
 return f

@g
def f():
 print("This is F.")
 return 1
'''
--------------------------------------------
Here it is.G
>>> f()
Here it is.F
'1'
'''

It worked. But .... What about the "print log function", # Yes, "Here is G" is the log I want!

Suspect one. The printout of "Here is G" is the first line, which occurs before typing "f()". ....

Suspect two.After typing "f()", "here is G" didn't come out .....

#Looking at the g-function alone, it's not really a "higher-order function." #

As a success story, it's a big failure.

##All right, I give up, it's not much fun to resist .....

Closures teach us that the best thing you can do to ensure that the return value is always a function is to "create a function inside the function, on the spot, and then throw it out."

def g(f):
 print("This is G.")
 def h():
  print('Here's H')
  return "H"
 return h

@g
def f():
 print("This is F.")
 return 1
'''
--------------------------------------------
Here it is.G
>>> f()
Here it is.H
'H'
>>> f()
Here it is.H
'H'
>>> 
'''

The f function doesn't work anymore. Yes, that's right. I tried it one more time.

Also, only the inside of the two logs can be used ...... (explained below)

I read that if the h function returns f(), then the f function can be executed. ,,,,, Personally, I think the decorator should be called "hijacker".

def g(f):
 print("This is G.")
 def h():
  print('Here's H')
  return f()
 return h

@g
def f():
 print("This is F.")
 return 1
'''
--------------------------------------------
Here it is.G
>>> f()
Here it is.H
Here it is.F
'1'
>>> f
<function g.<locals>.h at 0x0000020CBDBB6C80>
'''

Explain it along the lines of the book

'''
@g
def f():
 pass
>>>f()
is equivalent to
>>>g(f) ()
The g function executes and returns
>>>h ()
h function execution (print log)
>>>f()
f execution, return 1
>>>1
'''

With the addition of the parameter.

def g(f):
 print("This is G.")
 def h(*args,**kw):
  print('Here's H')
  return f(*args,**kw)
 return h

@g
def f(*args,**kw):
 print("This is F.")
 return "1"
'''
>>>f(*args,**kw)
Equivalent to
>>>g(f) (*args,**kw)
The g function executes and returns
>>>h (*args,**kw)
h function execution (print log)
>>>f (*args,**kw)
f execution, return 1
>>>1
'''

It can be seen, (*args,**kw) this change is taken by the h function, so, observing the h function, h gives its arguments to f as is.

I've got an idea. I've got an idea.

def g(f):
 print("This is G.")
 def h():#h didn't ask for parameters
  print('Here's H')
  return f
 return h

@g
def f(*args,**kw):
 print("This is F.")
 return "1"
'''
>>>f()(*args,**kw)
Equivalent to
>>>g(f) ()(*args,**kw)
The g function executes and returns
>>>h ()(*args,**kw)
h function executed, h takes the empty argument
(print log)
>>>f(*args,**kw)
f execution, return 1
>>>1
'''

But here comes a new problem, you have to add more empty brackets when you call f later on, or else

'''
>>>f(*args,**kw)
Equivalent to
>>>g(f) (*args,**kw)
The g function executes and returns
>>>h (*args,**kw)
h function execution (print log) return f
>>>f
This is a function object
'''

The above tells us one thing: "Whether a function executes or not depends on whether or not there are parentheses after it."

give an example

def m(a):
 print(a)
 return m

print(m(1)(2)(3)(4)(5)(6)(7)(8)(9)(10))
'''
-----------------------------
2
4
6
8
10
<function m at 0x000002832BDB10D0>

brainstorming session

f = ()()[0]()[d()()[e]]

The c method of class b of module a is a higher-order function that ultimately returns a list with a function in it

The function returns another dictionary ............

The above this talk about python decorator exploration and parameter collection is all that I have shared with you, I hope to give you a reference, and I hope that you will support me more.