python advanced syntax

exception handling

  • First of all we need to understand what is an "exception"?

    • In the process of running the program, there will always be various problems and errors.
    • Some errors are of our own making when we write the code:
      • Such as syntax errors, calling errors, and even logic errors.
    • There are also some errors, which are unforeseen errors, but are entirely possible:
      • Such as file does not exist, insufficient disk space, network congestion, system errors, etc.
    • These errors that cause abnormal interruption and exit of the program during the running process are collectively referred to as exceptions. Most exceptions are not handled by the program, but are displayed in the form of error messages.
    #0 cannot be used as a divisor
    1/0
     The exception information is: ZeroDivisionError: division by zero
    
  • Exception classification:

    • There are many types of exceptions. Python has dozens of built-in common exceptions, which can be used directly without special import.
    • It should be noted that all exceptions are exception classes, and the first letter is capitalized!
  • Unusual hazards:

    • If there is an abnormal statement code in the program, the exception will immediately interrupt the operation of the program!
  • therefore:

    • In order to ensure the normal operation of the program, improve the program robustness and availability. We should try to be comprehensive and handle possible exceptions instead of leaving them there and letting them happen.
  • python's mechanism for handling exceptions:

    • Python has a built-in try...except...finally(else)... exception handling mechanism to help us handle exceptions. Its basic syntax is:

    • try:
          pass
      except Exception as ex:
          pass
      
    • Mechanism Description:

      • First, the try clause (the statement between the keyword try and the keyword except) is executed

      • If no exception occurs, the except clause is ignored and the try clause is executed.

      • If an exception occurs during the execution of the try clause, the remainder of the try clause is ignored. If the type of the exception matches the name after the except, the corresponding except clause will be executed.

      • try:
            print("The statement before the exception is executed normally")
            print(1/0)
            print("Statements after the exception are not executed")
        except ZeroDivisionError as e:
            print(e)
        
    • If the exception occurred in the program is not in your catch list, other exceptions will still be thrown:

    • # The exception is not caught, and the program reports an error directly
      s1 = 'hello'
      try:
          int(s1)
      except IndexError as ex:    # This example is an illegal value exception, and you only catch the index exception
          print(ex)
      
      
  • What is Exception?

    • Among Python's exceptions, there is a general exception: Exception, which can catch any exception.
    • Thinking: Since there is an exception that can manage everything, can other exceptions such as OSError and ZeroDivisionError be unnecessary?
      • of course not! In many cases, the program will only pop up a few exceptions, and it is not necessary to catch all the exceptions, which will be very inefficient. In addition, it is necessary or even mandatory to formulate different handling measures according to different types of exceptions to accurately determine the type of errors and store error logs.
    • Common exception types:
    exception nameexplain
    AttributeErrorAttempt to access a property that an object does not have
    IOErrorinput/output exception
    ImportErrorUnable to import module or package; mostly path problem or wrong name
    IndentationErrorIndentation error
    IndexErrorsubscript index error
    KeyErrorAttempt to access a key that does not exist
    KeyboardInterruptCtrl+C is pressed, the keyboard terminates the input
    NameErroruse of undefined variable
    SyntaxErrorGrammatical errors
    TypeErrorThe type of the incoming object does not meet the requirements
    UnboundLocalErrorAttempt to access a local variable that has not been set
    ValueErrorPassing in a value not expected by the caller, even if the value is of the correct type
    OSErrorOperating system execution error
  • Python's exception mechanism has the ability to nest processing:

    For example, when the function f3() calls f2(), and f2() calls f1(), although there is an error in f1(), you only need to perform exception capture in f3(), and you do not need to capture exceptions at each layer.

    #function nesting exception
    def f1():
        return 10/0
    
    def f2():
        f1()
    
    def f3():
        f2()
    
    f3()
    

    Function nesting to handle exceptions:

    def f1():
        return 10/0
    
    def f2():
        f1()
    
    def f3():
        f2()
    
    try:
        f3()
    except Exception as e:
        print(e)
    
  • Nesting of try...exception

    As we said before, it's not just about using the general exception class Exception. For efficiency, we need to accurately capture common exception information. If the exception occurs in the user layer, it is necessary to perform user operations. The abnormality that occurs is judged and then accurately captured. How to operate it?

    • If an exception does not match any except, then the exception will be passed to the upper try. That is, the nested processing capability mentioned earlier. If it has not been caught until the very top of the program, an exception will pop up.

    • try:
          try:
              print("The statement before the exception is executed normally")
              print(1/0)
              print("Statements after the exception are not executed")
          except ValueError as e:
              print(e)
      
      except ZeroDivisionError as e:
          print("I didn't do a good job on the inner layer, I can only work hard on the outer layer.")
      
    • Or use the form of a try and multiple except s:

    • try:
          print("The statement before the exception is executed normally")
          print(1/0)
          print("Statements after the exception are not executed")
      except NameError as e:
          print(e)
      except ZeroDivisionError as e:
          print("I am the first to catch a divide by zero exception")
      except (ValueError,ZeroDivisionError) as e:
          print("I am the spare tire")
      
    • Or follow except with a tuple containing multiple exception classes

    except (RuntimeError, TypeError, NameError):
          pass
    
  • finally and else clauses

    The try except syntax also has an optional else clause which, if used, must be placed after all except clauses. This clause will be executed if no exception occurs in the try clause:

    Likewise, there is an optional finally clause. The finally clause is executed regardless of the execution of the try and the triggering of the except exception!

    Of course, when else and finally exist at the same time:

    try:
        pass
    except:
        pass
    else:
        print("else")
    finally:
        print("finally")
    
  • Actively throw an exception: raise

    Many times, we need to actively throw an exception. Python has a built-in keyword raise that can actively trigger exceptions.

    doubt:

    • Why throw exceptions yourself? Isn't it too much? Because sometimes, you need to record the error information, and then continue to pass the exception to the upper layer, and let the upper layer handle the exception, as follows:

    • try:
          divNum = input('enter a divNum:')
          divNum = int(divNum)
      
          try:
              1/divNum
          except ZeroDivisionError as ex:
              print("Record exception log: ", ex)
              print("But I can't handle it myself, I can only continue to throw it and see if the upper layer can handle it (throwing the pot)")
              raise ValueError('illegal entry')
      except Exception as e:
          print(e)
          print('User entered illegal data, please re-enter!')
      
    • Sometimes, you need to actively pop an exception, as a warning or special handling:

    • #Users enter their own gender: 1 for male, 2 for female
      sex = int(input("Please input a number: "))
      
      try:
          if sex == 1:
              print("This is a man!")
          elif sex == 0:
              print("This is a woman!")
          else:
              print("As if something out of the ordinary happened! !")
              raise ValueError("illegal input")
      except ValueError:
          print("This is a monster!")
      

iterator

Before introducing iterators, first explain the concept of iteration:

  • Iterate:

    • The process of traversing each element of the "object" through a for loop.
    • The object here refers to the iterable object. So remember: the for loop iterates over only iterable objects.
  • Objects of iterable types:

    • In Python, list/tuple/string/dict/set/bytes are all iterable data types/iterables!
  • How to determine whether an object is an iterable object? (learn)

    • You can use the Iterable type of the collections module in isinstance to determine whether an object is iterable

    • from collections import Iterable
      print(isinstance('abc',Iterable))
      
  • iterator

    • An iterator is an object that can be traversed and can be used with the next() function.

    • nature:

      • Iterator objects are accessed from the first element of the collection until all elements have been accessed. Iterators can only be traversed backwards and cannot be backtracked. Unlike lists, you can fetch the following data at any time, or you can return to the head to fetch the previous data.
    • Iterators usually implement two basic methods: iter() and next().

    • Notice:

      • Iterable objects are not necessarily iterators!
      • Common data structures, strings, lists, and tuples are all iterable objects, not iterators!
    • How to create an iterator?

      • String, list or tuple objects, and even custom objects can be used to create iterators:

      • #Create an iterator object using Python's built-in iter() method
        lis=[1,2,3,4]
        it = iter(lis)
        
      • You can use type to see the difference between list and iterator types:

      • lis=[1,2,3,4]
        it = iter(lis)
        print(type(lis),type(it))
        
      • Use the next() method to get the next element of the iterator:

      • lis=[1,2,3,4]
        it = iter(lis)
        print(next(it))
        print(next(it))
        
      • Use a for loop to iterate over the iterator:

      • lis = [1,2,3,4]
        it = iter(lis)          # Create an iterator object
        for x in it:            # Use a for loop to iterate over an iterable object
            print (x, end=" ")
        
  • Think: What is the role of iterators?

    • Advantages and disadvantages of iterable objects:
      • Advantages of iterable objects: You can visually view the objects inside, such as directly viewing the contents of a list
      • Disadvantages of iterable objects: all content needs to be loaded into memory, so it takes up memory
    • Advantages and disadvantages of iterators:
      • advantage:
        • Provides a general index-independent iterative value acquisition method;
        • To save memory, the iterator is equivalent to occupying only one piece of data in memory: because each time a value is taken, the previous piece of data will be released in memory, and the current piece of data will be loaded.
      • shortcoming:
        • Because there is a next method, that is, it can only take values ​​backwards, not forwards. The value selection is not as flexible as the index method, and a specified value cannot be taken.
        • Unable to predict the length of the iterator
  • Summary: What is the difference between iterators and iterables?

  • 1.anything that can act on for The objects of the loop are all iterable types;
    
    2.anything that can act on next()The objects of the function are all iterator types;
    
    3.list,dict,str etc is an iterable but not an iterator because next()Functions cannot call them. able to pass iter()The function converts them into iterators.
    
    
  • custom iterator

    • Many times, in order to make our own class an iterator, we need to implement the __iter__() and __next__() methods in the class

      • In fact, when using the next() function, the __next__ method of the iterator object is called
      • python requires the iterator itself to be iterable, so we also need to implement the __iter__ method for the iterator, and the __iter__ method returns an iterator.
        • The iterator itself is an iterator, so the __iter__ method of the iterator can return itself
    • #Iteratively generate the squared value of the specified range of series
      class Squares:
          def __init__(self, start, stop):  # Iteration start and stop bits
              self.start = start
              self.stop = stop
      
          def __iter__(self):     # an iterator that returns itself
              return self
      
          def __next__(self):     # return next element
              if self.start > self.stop:   # throw exception at the end
                  raise (StopIteration)
              item = self.start**2
              self.start += 1
              return item
      
      if __name__ == "__main__":
          for i in Squares(1, 5):
              print(i, end=" ")
      

derivation

  • The Python language has a unique syntax, which is equivalent to the existence of syntactic sugar, which can help you write more concise and cool code in certain situations. But without it, there won't be much impact. The Python language has several different types of comprehensions

    • list comprehension
    • dictionary comprehension
    • set comprehension
    • Tuple comprehension?
  • 1. List Comprehension

    • List comprehensions are a fast way to generate lists. It takes the form of a statement enclosed in square brackets, as shown in the following example:

    • alist = [x*2 for x in range(1,10)]
      print(alist)
      ############The upper and lower sets of codes are equivalent
      alist = []
      for x in range(1,10):
          alist.append(x*2)
      print(alist)
      
  • To understand the list comprehension formula in this way, first execute the for loop, and for each x traversed, substitute it into the x*2 expression to perform the operation, add the operation results one by one to a new list, and end the loop to get the final list. It is equivalent to the following code:

  • alist = []
    for x in range(1,10):
    	alist.append(x*2)
    print(alist)
    
    • effect:

      • List comprehensions give us a way to generate lists that implement more complex logic in one line. Its core syntax is to encapsulate the generation logic with square brackets []. Of course, list comprehensions can also be used in various ways.
  • Add conditional statement

  • alist = [x * x for x in range(1,11) if x % 2 == 0]
    print(alist)
    
    ##############Equivalent to the following code
    alist_1 = []
    for x in range(1,11):
        if x % 2 == 0:
            alist_1.append(x*x)
    print(alist_1)
    
  • multiple loops

    • re = [a+b for a in '123' for b in 'abc']
      print(re)
      
      #############
      alist = []
      for a in '123':
          for b in 'abc':
              alist.append(a+b)
      print(alist)
      
  • 2. Dictionary comprehension

    • Since you can write list comprehensions using square brackets [], what about using curly brackets? you guessed right! Use curly braces {} to make dictionary comprehensions!

    • dic = {x:x**2 for x in [2,4,6]}
      print(dic)
      
      '''
      dic = {}
      for x in [2,4,6]:
          dic[x] = x**2
      '''
      
    • Pay attention to the writing method of x: x**2, the colon in the middle means that the left side is the key and the right side is the value.

  • 3. Set derivation

    • In addition to being used for dictionary comprehensions, curly braces can also be used for set comprehensions, with only minor differences.

    • a = {x for x in 'aabbccddeeff'}
      print(a)
      
  • 4. Tuple comprehension

    • Use square brackets and curly brackets, then use parentheses, is it a tuple comprehension? The idea is good, but the fact is not. Parentheses are used as generator syntax in Python, and as we'll see shortly, there are no tuple comprehensions.

    • a = (x for x in 'aabbccddeeff')
      print(a)
      #<generator object <genexpr> at 0x102f45970>
      #Returns a generator object
      

Builder

  • Generators are undoubtedly one of the most useful features in the language of Python. At the same time, one of the least widely used Python features

    • The reason is mainly because there is no concept of generators in other mainstream languages. It is precisely because the generator is a "new" thing that on the one hand, it has not attracted the attention of the majority of engineers, and on the other hand, it has also increased the learning cost of engineers, and finally caused everyone to miss such a useful feature in Python. So what exactly is a generator?
  • Sometimes, the number of elements in a sequence or set is very large, and if all are manufactured and put into memory, the pressure on the computer is very large.

    • For example, suppose you need to get a huge data sequence of 10 to the 20th power, generate each number, and put it in a list in memory. If you use this crude method, you can ensure that your computer will have So much memory?
    • Then if the element can be calculated according to a certain algorithm, which element is calculated if the element is needed, then the subsequent elements can be continuously calculated in the process of the loop without creating a complete set of elements, thus saving a lot of space . In Python, this mechanism of calculating elements while looping is called a generator: generator.
    • Therefore: a generator is a special kind of iterator, the generator automatically implements the "iterator protocol" (that is, the __iter__ and next methods), and there is no need to manually implement the two methods.
  • Next, let's take a look at how to create a generator! 2 ways

    • generator comprehension (ignored)
    • for loop, yield keyword
  • 1. Generator derivation:

    • a = (x for x in 'aabbccddeeff')
      print(a)#generator object
      
    • The next return value of the generator can be obtained through the next() function:

    • a = (x for x in 'aabbccddeeff')
      print(next(a))
      print(next(a))
      print(next(a))
      
    • But more often we use a for loop to iterate over the generator:

    • g = (x for x in range(5))
      for i in g:
          print(i)
      
  • 2, yield keyword creation generator (emphasis)

    • In Python, a function returned with yield becomes a generator. In the process of calling the generator, every time yield is encountered, the function will pause and save all current running information, and return the value of yield. And continue running from the current position the next time the next() method is executed. The following focuses on understanding the use of the yield keyword:

      • yield is a keyword similar to return, except this function returns a generator
      • When you call this function, the code inside the function is not executed immediately, this function just returns a generator object
      • When you use for to traverse or call the next function, the code in the function will be executed
    • Simple sample code: The function body returns a generator through a for loop combined with yield

    • def createGenerator():
          for i in range(5):
              print('I am the body of the loop!')
              yield i*i #Use yield instead of return
      g = createGenerator()
      print(g)
      #<generator object createGenerator at 0x104bc5970>
      v1 = next(g)
      print(v1)
      #I am the body of the loop!
      #0
      v2 = next(g)
      print(v2)
      #I am the body of the loop!
      #1
      
    • Consider: What is the result of the execution of the following function?

      • def yieldTest():
            i = 0
            while i < 3:
                temp = yield i #The assignment statement must be executed first on the right side of the equal sign, and on the left side of the equal sign.
                print(temp)
                i += 1
             #Inside the generator function implementation, you can write code behind yield
                
        obj = yieldTest()#Create a generator object
        v1 = next(obj)
        print(v1) #Execution result: 0
        
        v2 = next(obj)
        print(v2) #Execution result: None 1
        
      • Think about how None is generated for the first time: yield returns the i value of 0, stops at yield i, and temp is not assigned a value. The second time the value is taken, it starts at print, and temp is not assigned, so print None, add 1 to i, continue while judgment, yield returns i value 1, stop at yield i)

decorator

  • Decorator:

    • Literally, it is the device that decorates the object.

    • That is, new functions or additional restrictions can be added to the decorated object without modifying the original code.

    • There are many kinds of decorators, including function decorators and class decorators. Decorators have different names in many languages, and they reflect the decoration pattern in the design pattern.

    • The syntax of a decorator is to put @decorator name above the decorated object.

    • @dec
      def func():
        pass
      
  • #Requirement: Add a print "register function" to the func function
    #define decorator
    def outer(f):#2. The f here is the function func (the decorated function), that is to say, adding the decorator will pass the name of the decorated function to the parameter f
        def inner():
            #6. Execute the inner function body operation
            f() #6.1. Call the original func function
            print('Registration function') #6.2 Implementing new functions added
        return inner #3. The return value here will be returned to the name of the decorated function
    
    @outer  #1. Call the outer decorator function
    def func(): #4. func == inner
        print('Login function')
    
    func() #5.func() == inner()
    
    
  • Before introducing decorators, we must first clarify several concepts and principles:

    • First of all, the Python program is executed sequentially from top to bottom, and the defined code block of the function will not be executed immediately. Only when the function is called will the internal code block be executed.
    • Second, because of sequential execution, if you do define the same function twice, the later definition will override the earlier one. Therefore, the placement of the code in Python is different and cannot be placed arbitrarily. Usually, the function body should be placed before the calling statement.
  • virtual scene

    • There is a large company, and its basic platform department is responsible for the development of internal applications and API s. In addition, there are hundreds of business departments responsible for different businesses. These business departments call different functions provided by the basic platform department, that is, API s to process their own business. The situation is as follows:

    • #The basic platform department has developed API s for hundreds of functions
      def f1():
      	print('Data Interface for Business Unit 1......')
      def f2():
      	print('Data interface for business unit 2......')
      def f3():
      	print('Data Interface for Business Unit 3......')
      def f100():
      	print('Data Interface for Business Unit 100......')
        
      #Each part calls its own part of the API
      f1()
      f2()
      f3()
      f100()
      
    • The basic platform department developed these functions when the company was still in its early days. For various reasons, such as time constraints, lack of manpower, architectural flaws, ill-consideration, etc., there is no security certification for function calls. Now that the company has grown and grown, it can no longer go down like the "grass stage team" in the start-up period. The director of the basic platform department decided to make up for this defect, so:

      • Day 1: The supervisor called an operation and maintenance engineer, and the engineer ran up and down to notify department by department, asking them to add the authentication function to the code, and then he was fired that day.

      • Day 2: The supervisor called a python automation development engineer. This is what my buddies did. Only the code of the basic platform was refactored, so that N business departments did not need to make any changes. This guy was also fired soon, and he didn't even have to do operation and maintenance.

      • #The basic platform department has developed API s for hundreds of functions
        def f1():
          #Add Authenticator Code
          xxx
        	print('Data Interface for Business Unit 1......')
        def f2():
          #Add Authenticator Code
          xxx
        	print('Data interface for business unit 2......')
        def f3():
          #Add Authenticator Code
          xxx
        	print('Data Interface for Business Unit 3......')
        def f100():
          #Add Authenticator Code
          xxx
        	print('Data Interface for Business Unit 100......')
          
        #Each part calls its own part of the API
        f1()
        f2()
        f3()
        f100()
        
      • Day 3: The supervisor has another development engineer. Here's what he did: define an authentication function and call it in other original functions. The code is as follows:

      • #The basic platform department has developed API s for hundreds of functions
        def cheak():
          pass
        def f1():
          cheak()
        	print('Data Interface for Business Unit 1......')
        def f2():
          cheak()
        	print('Data interface for business unit 2......')
        def f3():
          cheak()
        	print('Data Interface for Business Unit 3......')
        def f100():
          cheak()
        	print('Data Interface for Business Unit 100......')
          
        #Each part calls its own part of the API
        f1()
        f2()
        f3()
        f100()
        
      • But the supervisor was still not satisfied, but this time he explained why.

        • The supervisor said: Write code to follow the principle of open and closed. In short, the internal function code that has been implemented is not allowed to be modified, but the external can be extended. If the open-closed principle is applied to the above requirements, then code modifications are not allowed inside functions f1, f2, f3...f100, but they can be extended outside.
      • Day 4: There is no time for the supervisor to find someone else to do this work, he decides to go into battle himself, use the decorator to complete this task, and plans to add a logging function after the function is executed. The supervisor's code is as follows:

      • def outer(func):
          def inner():
            print('Authentication function operation')
            result = func()
            return result
          return inner
        
        #The basic platform department has developed API s for hundreds of functions
        @outer
        def f1():
        	print('Data Interface for Business Unit 1......')
        @outer  
        def f2():
        	print('Data interface for business unit 2......')
        @outer
        def f3():
        	print('Data Interface for Business Unit 3......')
        @outer
        def f100():
        	print('Data Interface for Business Unit 100......')
          
        #Each part calls its own part of the API
        f1()
        f2()
        f3()
        f100()
        
      • Using the decorator @outer, it is only necessary to expand the code of the basic platform, so that the authentication operation can be performed before other departments call the function API, and other business departments do not need to make any modifications to their own code, and the calling method does not need to be Change.

  • Decorator mechanism analysis

    • The following takes the f1 function as an example to analyze the operation mechanism of the decorator:

    • #1. Define a decorator
      #The decorator outer has special requirements:
      #Requirement 1: The decorator function must have one parameter (representing the function name of the decorated function)
      def outer(func): #step2.func == f1
          def inner():
              print('Give f1 Function added security authentication function')
              func() #step3: Equivalent to calling f1()
              print('Give f1 The function adds the function of data detection')
          return inner#step4: inner represents the name of the internal function, which will replace the decorated function name
      #2. Use the defined decorator to decorate a function (add new functions to it without modifying the original code of the function)
      #If the decorator decorates a function, the decorator function will be called automatically
      @outer # step1. Call the decorator function and pass the decorated function name to the parameter of the decorator function
      #Decorate the f1 function with the outer decorator
      def f1(): #step5: f1 == inner; inner() function call is calling f1()
      	print('Data Interface for Business Unit 1......')
      def f2(): #f2 is not decorated by outer
          print('f2 The original implementation of the function')
      
      f1() #is actually calling inner()
      
      
      - 1.The program starts running, explained from top to bottom, reads def outer(func):When I found that this was a function definition, I loaded the function body into memory.
      
      - 2.read@outer , the program is@This syntax is attractive, the interpreter knows that this is a decorator, and it is expected to be executed immediately, so the program starts to run@the name behind outer the defined function.
      
      - 3.program returns to outer function, which starts to execute the syntax rules of the decorator. The rules are:
        - The name of the decorated function will be passed as an argument to the decorated function. After the decorated function executes its own internal code, it assigns its return value to the decorated function. The original f1 The function is passed as a parameter to func,and f1 This function name will then point to inner function.
      
      - Notice:
        - @outer and@outer()There is a difference, when there are no parentheses, outer The function will still be executed, which is different from the traditional parentheses to call the function, special attention is needed!
        - f1 This function name is passed as a parameter to the decorated function outer,That is: func = f1,@outer equal outer(f1),actually passed f1 the body of the function instead of executing f1 the return value after.
        - outer function return yes inner this function name, instead of inner()The return value after being called like this
      
      - 4.program starts outer The content inside the function, at the beginning it encounters another function inner,inner The function definition block is not executed immediately after being observed by the program, but is read into memory (this is the default rule).
      
      - 5.further down, meet return inner,The return value is a function name, and this function name will be assigned to f1 This decorated function, which is f1 = inner. From the previous knowledge, we know that at this time f1 function is new function inner covered (actually f1 Change the function name to point to inner The memory address of the function body pointed to by this function name, f1 no longer points to the memory address of its original function body), and then calls f1 will execute when inner The code inside the function, not the previous function body. So where did the previous function body go? Remember we will f1 passed as a parameter to func Is this parameter? func This variable holds the address of the old function in memory, through which the old function body can be executed. inner seen in the function result = func()This code, it does just that!
      
      - 6.Next, it's not over yet. When the business department, still through f1()way to call f1 function, the execution is no longer the old one f1 function code, but inner code for the function.
      
      - 7.After the above process is completed, you should see that while no modification was made to the code and interface calling method of the business department, there was no internal modification to the original code of the basic platform department, but only a decoration function was added. , which achieves our needs, authenticates before the function call, and writes the log after the call. That's what decorators do best.
      
    • Thinking: Why do we have to make an outer function and an inner function so complicated? A layer of functions is not enough?

      • Please note that the code @outer will automatically execute the code inside the outer function when the program is executed here. If it is not encapsulated, it will be executed before the business department calls it, which is inconsistent with the original intention. Of course, if you have a need for this, it's not impossible.
  • With parameter decorator

    • In the above example, the f1 function has no parameters. In actual situations, parameters will definitely be required. How are the parameters of the function passed?

    • Add a parameter to the definition part of the inner function, and pass this parameter when calling the func function:

    • def outer(func):#2.func == f1
          def inner(n): #3.n == name,n is the parameter of the decorated function
              print('new function!')
              func(n) #4.func(n) == f1(n)
          return inner #5.inner will overwrite the original decorated function name f1
      
      @outer #1. Call the decorator function, pass the decorated function name f1 as an actual parameter, and pass it to the formal parameter of outer
      def f1(name): #6.f1 == inner
          print('f1 the original function, f1 The parameter value is:',name)
      
      f1('bobo') #7.inner('bobo')
      

Tags: Python programming language

Posted by access9 on Mon, 24 Oct 2022 06:43:55 +1030