Python Interview [11] - A comprehensive list of Python iterable objects

iterable object

Insert image description here

  1. Iterable objects are the basis of iterators and generators. Simply put, objects that can be traversed using a for loop are iterable objects, such as common lists, sets, and dicts.
  2. In python, an iterable object refers to an object that implements the **iter(**) method. When we use a for loop When traversing an iterable object, you actually call the __iter__() method of the object to obtain an iterator, and use the iterator to iterate through the elements of the object.
  • Common types:
    • (1) All sequence types: such as: list, str, tuple, range
    • (2) Non-sequence types: dict, set, file objects: f = open(xx, )

Python iterators and generators

1) Iterator

  • An iterator is an object in python that implements the iteration protocol. It is essentially a python data structure that implements two magic methods: iter() and __next__() methods, collectively called the iterator protocol. Among them, the iter() method returns the iterator itself, next() Method returns the next value in the sequence.
  • Iterators can support for loops and next() function calls. On each iteration, the iterator will produce a value until there is no next value, and a StopIteration exception will be thrown.
  • How to determine whether an object is an iterator is similar to the method of determining whether it is an iterable object. Just replace Iterable with Iterator.

2) Generator

1.	def spam():
2.	    yield”first”
3.	    yield”second”
4.	    yield”third”
5.	for x in spam:
6.	Print(x)
7.	-----结果如下-----
8.	first
9.	second
10.	third

1 When we create the list, due to memory constraints, the capacity is definitely limited, and it is impossible to enumerate them all at once. A fatal shortcoming of Python's commonly used list generation is that it is generated upon definition, which is a huge waste of space and efficiency.
2 If the list elements can be calculated according to a certain algorithm, then the subsequent elements will be continuously calculated during the loop, so that there is no need to create a complete list, thus saving a lot of space. In python, this mechanism of looping and calculating at the same time is called a generator: generator. In contrast to dictionaries and sets, generators are a classic example of time-for-space.
3 The easiest way to create a generator is to transform the list generation, and the generator function, defined by def, and then use yield to support the iterator protocol, which is easier to write than iterators. Simple.
4 When making a function call, return a generator object. When calling next(), it will return when yield is encountered and record the function call position at this time. The next time next() is called, it will start from the breakpoint.
5 We can use generators just like iterators. Of course, in addition to definition, to define an iterator, we need to implement the iter() and next() methods respectively, but generators only need yield.

The difference between iterable objects and iterators

  1. Different definitions:
  • Iterable: An iterable object refers to a function that implements the iter() method, which returns an iterable object.
  • Iterator: An iterator refers to an object that implements the iter() and next() methods. The iter() method returns the iterator itself, and the next method returns the next element of the iterator, and a StopIteration exception is raised at the end.
  1. Different ways of use:
  • Iterable: Iterable objects can be accessed iteratively using functions such as for loops and list(). In a for loop, the iterator's next() method is automatically called until a StopIteration exception is thrown. Iterable objects can be accessed by converting them into lists using the list() function.
  • Iterator: The iterator needs to use the next() function to get the next element. When the iterator has traversed all elements, it will automatically throw a StopIteration exception. In addition, iterators can only traverse in one direction, not in the reverse direction.
  1. Memory status:
  • Iterable: When an iterable object is accessed iteratively, it will not remember the previous access status, and it will be traversed from the beginning every time.
  • Iterator: When the iterator performs iterative access, it will remember the previous access status. Each time the next() method is called, it will start traversing from the last stop position.

12. The difference between generators and iterators

Although both generators and iterators can be used for for loop traversal, there are significant differences between them:

  1. Different implementation methods
    The generator uses the yield statement to implement it, while the iterator uses the magic functions __iter__() and __next__() to implement it.
  2. The generation method is different
    The generator can generate the values ​​in the sequence one by one, while the iterator generates the entire sequence at once and stores it in memory.
  3. Execution is different
    Generators can be called like functions and can produce and restore values ​​at each iteration, while iterators are executed sequentially according to the next element of the sequence.
  4. Different functions
    Generators are mainly used to generate sequences, while iterators are mainly used to traverse sequences.

What is a decorator?

The decorator is essentially a function, which can add functionality to existing functions without making any changes.
Decorators allow adding some extra functionality to an existing function by passing it to the decorator, which will perform the functionality of the existing function and add the extra functionality.
Two major features of decorators:

  • Ability to replace decorated functions with other functions
  • The decorator is executed immediately when the module is loaded

Eg: Write a decorator that records function execution time [Frequent Interview Test]:

 1. from time import time
 2.  
 3. def record_time(func):
 4.     def inner(*args, **kwargs):  # 这里的*args和**kwargs用来接收被装饰的函数的参数
 5.         """函数注释:用来修饰被装饰函数的内嵌函数"""
 6.         start = time()
 7.         result = func(*args, **kwargs)  # result用来接受被装饰的函数的返回值
 8.         end = time()
 9.         print(f"被装饰的函数{
      
      func.__name__}的执行时间为:{
      
      end - start}")
10.         return result + '~~~~~~'   # 对被装饰的函数的返回值进行修饰
11.  
12. return inner

The record_time function defined above is a decorator, and the embedded function inner + external function parameter fun constitutes a closure.

  • Usage method 1:
 1. def countdown(n):
 2.     """函数注解:这是一个倒计时函数"""
 3.     print("开始倒计时")
 4.     while n > 0:
 5.         n -= 1
 6.     print("倒计时结束")
 7.     return "我执行完啦"
 8.  
 9. # 使用方法1
10. countdown = record_time(countdown) # countdown是 record_time 函数中返回的 inner 函数
11. res = countdown(1000000)   # 执行 inner 函数,将 inner 函数的返回值给 res
12. print(res)

  • Usage method 2:
 1. @record_time	# 对人类更友好的语法糖写法
 2. def countdown(n):
 3.     """函数注解:这是一个倒计时函数"""
 4.     print("开始倒计时")
 5.     while n > 0:
 6.         n -= 1
 7.     print("倒计时结束")
 8.     return "我执行完啦"
 9.  
10. res = countdown(10000000)   # 被装饰完的 countdown 虽然看起来和调用方式都是 countdown,其实是它的本质是一个 inner 函数
11. print(res)

The principles of Grammar 1 and Grammar 2 are the same. Writing method 2 is the writing method of syntactic sugar. Syntactic sugar refers to those grammatical structures that do not add new functions or features to the computer language.

  • Writing specifications for syntactic sugar: write immediately above the decorated object. There must be no code between the syntactic sugar and the decorated object.
  • The internal principle of syntactic sugar: Syntactic sugar will automatically pass the name of the decorated object as a parameter to the decorator function call

What does function decorator do?

A decorator is essentially a Python function that allows other functions to add additional functionality without making any code changes. The return value of the decorator is also a function object, which is suitable for scenarios where aspects are needed. For example: Inserting logs, performance testing, transaction processing, caching, permission verification and other scenarios. Decorators are an excellent design to solve such problems. With decorators, we can extract a large number of similarities that have nothing to do with the function itself. code and continue to reuse it.

 1. def first(fun):
 2.     def second():
 3.         print('start')
 4.         fun()
 5.         print('end')
 6.         print fun.__name__
 7.     return second
 8.  
 9. def man():
10.     print('i am a man()')
11.  
12. f = first(man)
13. f()

Equivalent to

 1.  1. def first(func):
 2.  2.     def second():
 3.  3.         print('start')
 4.  4.         func()
 5.  5.         print('end')
 6.  6.         print (func.__name__)
 7.  7.     return second
 8.  8.  
 9.  9. @first
10. 10. def man():
11. 11.     print('i am a man()')
12. 12.  
13. 13. man()
14. ------ 结果 ------
15. Start
16. I am a man()
17. End
18. man

The code above does exactly the same thing as the previous code. The difference is that the previous code directly "blatantly" uses the first function to encapsulate the function, while the above one uses [syntax sugar] to encapsulate the man function. In the above code, [@first] is above the man function, which means using the first decorator on the man function. [@] is the syntax of the decorator, [first] is the name of the decorator.

One sentence explains what kind of languages ​​can use decorators

In languages ​​where functions can be passed as parameters, decorators can be used.

Scope in Python?

The language distinguishes scope in order to reuse variable names. Introducing scope is equivalent to dividing variables into their own "isolation areas". In different "isolation areas", it becomes easier to find variables. In Python, the scope of a variable depends on where it is defined. When Python encounters a variable, it will search in this order (from inside to outside):
Local scope (Local)–> Nested scope (Enclosing locals)–> Global Scope(Global)–>Built-in scope(Built-in)

  • Local scope: Its scope is inside a function/method. The parameters of the function, various variables or objects defined within the function all belong to the local scope
  • Nested scope: Mainly used in scenarios with nested functions to implement closures, variables defined in the function, outside the nested function, and referenced by the nested function
  • Global scope: Its scope is anywhere in the current module. Other modules, global variables, functions and classes defined in the top-level area of ​​the module all belong to the global scope.
  • Built-in scope: Its scope is anywhere in all modules. Python's built-in data types, built-in functions, standard exceptions, etc. all belong to the built-in scope.

What is closure

Closure refers to defining another function inside a function and returning the object as the function, while also saving the status information of the outer function. This nested function can refer to the variables and parameters of the outer function, and the outer function returns a reference to the nested function. This way of defining a function inside a function and returning it is called a closure. Closures extend the scope of nested functions, which mainly refer to non-global variables that are referenced in the function definition but not defined in the function definition body.

  • The following conditions must be met to create a closure:
    • There must be a nested function (embedded function: function defined inside the function)
    • Inline functions must reference variables in external functions [including parameters in external functions]
    • The return value of an external function must be an embedded function [The embodiment of a function as a first-class object: return the function like an ordinary variable]

おすすめ

転載: blog.csdn.net/s1_0_2_4/article/details/134896264