Python 基础面试第四弹
阅读原文时间:2023年09月01日阅读:1

1. Python中常用的库有哪些,作用分别是什么

  1. requests: requests 是一个用于发送 HTTP 请求的库,它提供了简单而优雅的 API,可以轻松地发送 GET、POST、PUT、DELETE 等请求,并处理响应数据。它支持会话管理、身份验证、文件上传等常见的 HTTP 功能,是进行 Web 开发和 API 调用的常用选择。

  2. math: math 是 Python 的标准库之一,提供了许多数学运算相关的函数和常量。它包括基本的数学运算(如三角函数、指数函数、对数函数)、数学常量(如π和自然对数的基数e)、数学操作(如取整、绝对值、幂运算)等。math 库是进行数学计算和科学计算的基础。

  3. websocket: websocket 是一个用于创建和管理 WebSocket 连接的库。WebSocket 是一种在客户端和服务器之间实现全双工通信的协议,它允许服务器主动向客户端推送数据,而不需要客户端发送请求。websocket 库提供了用于创建 WebSocket 服务器和客户端的功能,使得在 Web 应用程序中实现实时通信变得更加容易。

  4. time: time 是 Python 的标准库之一,提供了与时间相关的功能。它包括获取当前时间、日期和时间的转换、时间戳的操作、睡眠(延迟执行)等功能。time 库广泛用于需要处理时间和日期的应用程序,例如定时任务、日志记录、性能分析等。

  5. pymysql: pymysql 是一个用于连接和操作 MySQL 数据库的库。它是 Python 的一个流行的数据库接口,提供了在 Python 中执行 SQL 语句、连接数据库、事务管理等功能。pymysql 库可以用于许多与数据库相关的任务,如数据查询、数据插入、数据更新等。

2. Python中的垃圾回收机制

在Python中,垃圾回收(Garbage Collection)是自动管理内存的过程,它负责检测和回收不再使用的对象占用的内存空间。Python使用了一种称为引用计数(Reference Counting)的垃圾回收机制,以及一个可选的循环垃圾回收器(Cycle Detector)来处理循环引用的对象。

引用计数:
Python中的每个对象都有一个引用计数器,用于记录当前有多少个引用指向该对象。当一个对象被引用时,它的引用计数增加;当一个引用被删除或超出作用域时,引用计数减少。当对象的引用计数变为0时,说明该对象没有被引用,即成为垃圾对象,可以被垃圾回收机制回收。

引用计数机制的优点是实时性高,当对象不再被引用时,可以立即回收内存。但它也存在一些缺点,例如无法处理循环引用的情况。

循环垃圾回收器:
为了解决循环引用的问题,Python中引入了循环垃圾回收器。循环垃圾回收器通过周期性地检测对象之间的引用关系,找到不再被引用的循环引用对象,并将其回收。它的工作原理如下:

  1. 标记阶段(Marking Phase):从根对象(如全局变量、活动栈、调用栈等)开始,通过遍历对象之间的引用关系,标记所有可以访问到的对象。
  2. 清除阶段(Sweeping Phase):遍历整个堆内存,清除未被标记的对象,并回收它们占用的内存空间。
  3. 压缩阶段(Compacting Phase):对堆内存进行整理,将存活的对象向一端移动,以便释放连续的内存空间。

循环垃圾回收器可以解决引用计数无法处理的循环引用问题,但它会增加垃圾回收的开销,并且在回收垃圾时可能会导致一些暂停。

其他优化技术:
除了引用计数和循环垃圾回收器之外,Python还使用了其他一些优化技术来改善垃圾回收的性能,例如:

  1. 分代回收(Generational Collection):根据对象的存活时间将其分为不同的代,采用不同的回收策略。大部分对象往往很快就变成垃圾,而只有少部分对象存活更久。通过针对不同代采用不同的回收频率,可以减少垃圾回收的开销。
  2. 增量回收(Incremental Collection):将垃圾回收过程分解为多个阶段,在每个阶段之间允许程序继续执行。这样可以将垃

3. python中的对象和引用的理解

在Python中,对象是数据的抽象表示,可以是数字、字符串、列表、函数等。对象在内存中占据一定的空间,并包含了数据和操作数据的方法。每个对象都有一个唯一的身份(Identity),可以通过内置函数id()获取。

引用是指向对象的标识符,可以将其视为指针或者别名。在Python中,通过变量名、数据结构中的元素、函数参数等方式创建引用。引用允许我们访问和操作对象,但并不直接存储对象本身,而是指向对象所在的内存地址。

下面我们详细讨论Python中的对象和引用的一些特性:

1. 对象的创建和销毁:
对象的创建是通过使用相应的构造函数或者字面值来实现的。例如,使用str()构造函数创建字符串对象,使用[]符号创建列表对象等。对象的销毁是通过垃圾回收机制来自动处理的,当对象不再被引用时,垃圾回收机制会回收其占用的内存空间。

2. 对象的身份(Identity):
每个对象在创建时都会分配一个唯一的身份,可以通过id()函数获取。对象的身份是在其生命周期中保持不变的,即使对象的值发生变化,其身份也不会改变。

3. 可变对象和不可变对象:
在Python中,对象可以分为可变(Mutable)对象和不可变(Immutable)对象。可变对象的值可以被修改,而不可变对象的值是不可改变的。例如,列表(list)是可变对象,可以通过修改元素来改变其值;而字符串(str)是不可变对象,一旦创建,其值就不能被修改。

4. 引用的赋值和传递:
在Python中,引用可以通过赋值操作进行创建和修改。当我们将一个对象赋值给一个变量时,实际上是将该对象的引用赋值给了变量。这意味着变量和对象之间建立了关联,但并不表示变量与对象是同一个实体。

在函数调用时,参数传递也是通过引用进行的。当我们将一个对象作为参数传递给函数时,函数内部的参数将引用该对象。这意味着函数内部对参数进行的修改可能会影响到原始对象。

5. 引用计数的影响:
引用计数是Python垃圾回收机制的核心。每个对象都有一个引用计数器,记录有多少个引用指向该对象。当引用计数变为0时,说明对象不再被引用,可以被垃圾回收器回收。引用计数机制的优点是实时性高,能够及时回收不再使用的对象,但无法处理循环引用的情况。

综上所述,Python中的对象是数据的抽象表示,通过引用来访问和操作对象。引用提供了对对象的别名或指针,允许我们在程序中使用对象。同时,垃圾回收机制通过引用计数和循环垃圾回收器来管理和回收不再使用的对象,确保内存的有效利用。

4. Python中单例模式的实现

在Python中,单例模式是一种设计模式,用于确保类只有一个实例,并提供全局访问点以获取该实例。单例模式通常用于需要共享资源或全局状态的情况,以避免创建多个实例造成资源浪费或状态不一致的问题。

下面是一种常见的Python单例模式的实现方式:

class Singleton:
_instance = None

def \_\_new\_\_(cls, \*args, \*\*kwargs):  
    if not cls.\_instance:  
        cls.\_instance = super().\_\_new\_\_(cls)  
    return cls.\_instance

在这个实现中,使用了类变量 _instance 来保存唯一的实例。在 __new__ 方法中判断 _instance 是否已经存在实例,如果不存在则创建一个新的实例,并将其赋值给 _instance。如果 _instance 已经存在实例,则直接返回该实例。

下面通过一个例子来说明如何使用该单例类:

class Logger(Singleton):
def __init__(self):
self.log = []

def add\_log(self, message):  
    self.log.append(message)

def print\_log(self):  
    for message in self.log:  
        print(message)

创建多个 Logger 实例

logger1 = Logger()
logger2 = Logger()

logger1 和 logger2 是同一个实例

print(logger1 is logger2) # 输出: True

向 logger1 添加日志

logger1.add_log('Log message 1')
logger1.add_log('Log message 2')

logger2 也能访问到 logger1 添加的日志

logger2.print_log()

输出:

Log message 1

Log message 2

5. Python 中常用的表达式:

6. 在 Python 中,什么是上下文管理器(Context Manager)?如何实现一个上下文管理器?

  在Python中,上下文管理器(Context Manager)是一种用于管理资源的机制,确保在代码块执行前后正确地获取和释放资源。上下文管理器通常与 with 语句一起使用,以确保资源的正确打开和关闭,即使在发生异常的情况下也能进行适当的清理。

要实现一个上下文管理器,需要定义一个类,并在该类中实现两个特殊方法:__enter__() 和 __exit__()

  1. __enter__() 方法:该方法在进入代码块之前被调用,并返回一个值,该值将由 as 语句后的变量接收。通常在该方法中进行资源的获取和初始化操作。

  2. __exit__() 方法:该方法在代码块执行完成后被调用,无论是否发生异常。它负责资源的释放和清理操作。__exit__() 方法接收三个参数:异常类型、异常值和跟踪信息。如果代码块正常执行完毕,这些参数都为 None。如果发生异常,可以在 __exit__() 方法中处理异常并返回 True,以指示异常已被处理。如果返回 False 或引发新的异常,则异常将向上层传播。

下面是一个简单的示例,展示了如何实现一个上下文管理器:

class MyContextManager:
def __enter__(self):
# 在进入代码块之前进行资源的获取和初始化
print("Entering the context")
return self # 可选择性地返回一个值给 as 语句后的变量

def \_\_exit\_\_(self, exc\_type, exc\_val, exc\_tb):  
    # 在代码块执行完成后进行资源的释放和清理  
    print("Exiting the context")  
    if exc\_type is not None:  
        # 处理异常并返回 True 表示异常已被处理  
        print(f"Exception occurred: {exc\_type}, {exc\_val}")  
        return True

使用上下文管理器

with MyContextManager() as cm:
# 在这里执行需要进行资源管理的代码块
print("Inside the context")
# 可以在代码块中引发异常来验证异常处理
# raise ValueError("Something went wrong")

7.  Python 中的异步编程,包括 async/await 关键字和 asyncio 模块的使用

在 Python 中,异步编程是一种编程模式,用于编写高效的非阻塞(non-blocking)并发代码。它允许程序在等待某些操作完成时继续执行其他任务,而不会阻塞整个程序的执行流程。

异步编程的关键部分是 async/await 关键字和 asyncio 模块。

  1. async/await 关键字:

    • async:用于定义一个异步函数。异步函数可以包含 await 关键字,表示在等待某些异步操作完成时暂停函数的执行。
    • await:用于等待一个异步操作的完成。它可以用于异步函数内部,暂停函数的执行并允许其他任务执行,直到异步操作完成并返回结果。
  2. asyncio 模块:

    • asyncio 是 Python 标准库中用于异步编程的模块。它提供了一组工具和函数,用于编写异步代码。
    • 主要的组件是事件循环(event loop),它负责调度和执行异步任务。事件循环允许多个任务并发执行,并在需要时挂起和恢复任务的执行。
    • asyncio 还提供了一些辅助函数和类,用于处理异步操作,例如异步 I/O 操作、定时器等。
    • 通过使用 asyncio 模块,可以编写基于回调、协程和任务的异步代码。

下面是一个简单的示例,展示了如何使用 async/await 和 asyncio 进行异步编程:

import asyncio

定义一个异步函数

async def greet(name):
print(f"Hello, {name}!")
await asyncio.sleep(1) # 模拟一个耗时的异步操作
print(f"Goodbye, {name}!")

创建一个事件循环

loop = asyncio.get_event_loop()

调用异步函数

tasks = [greet("Alice"), greet("Bob")]

将异步函数包装成任务对象

可以使用 asyncio.create_task() 或 loop.create_task() 创建任务

create_task() 是 Python 3.7 之后的新语法,推荐使用

tasks = [asyncio.create_task(greet("Alice")), asyncio.create_task(greet("Bob"))]

执行任务并等待完成

loop.run_until_complete(asyncio.wait(tasks))

关闭事件循环

loop.close()

在上面的示例中,greet() 是一个异步函数,使用 async 关键字进行定义。在函数内部,使用 await 关键字等待 asyncio.sleep(1) 的完成。通过创建任务对象,并使用事件循环的 run_until_complete() 方法来执行这些任务。最后,通过调用 loop.close() 关闭事件循环。

异步编程在处理 I/O 密集型任务(如网络请求、数据库访问等)时特别有效,因为可以在等待响应时充分利用 CPU 完成其他任务,从而提高程序的性能和响应能力。