返回顶部

面试7

1迭代器和生成器区别 ?

迭代器: 可以被next()函数调用,并不断返回下一个值的对象称为迭代器 。它内部有 next 方法和 iter 方法返回自己本身 ,在后台 for 语句 对容器象调用 iter()函数,iter() 会返回一个定义next()方法的迭代器对象,它在容器中逐个访问容器内元素,在没有后续元素时,next()会 抛出一个StopIter 异常。

生成器:在python中一边循环一边计算的机制,称为生成器。特点:只有在调用时才会产生相应的数据。Next方法只记录当前的值,打破了必须执行到底的局面,可以自由的进出循环,每调用一次,用一次next()方法。Send()方法。可以把值传给上次中断yeild的位置,然后执行。

区别:生成器能做到迭代器所有的事,在每次迭代获取数据(通过next()⽅法)时按照特定的规律进⾏⽣成。使用生成器可以同时节省内存。

2  线程、进程、协程

         进程:是一个整体的形式暴露给操作系统管理,里面包含对各种资源的调用,内存的管理,网络接口的调用等。由于进程比较重量,占据独立的内存,所以上下文进程间的切换开销比较大,但相对比较稳定安全。简单的说,就是对各种资源管理的集合。

         线程:线程是进程的一个实体,是操作系统最小的调度单位,是一串指令的集合。所有在同一个进程里的线程是共享一块内存空间的,线程是cpu执行时所需的。线程间通信主要通过共享内存,上下文切换很快,资源开销较少,但相比进程不够稳定容易丢失数据。

         协程:协程是一种用户态的轻量级线程,协程的调度完全由用户控制。协程拥有自己的寄存器上下文和栈。协程调度切换时,基本没有内核切换的开销,可以不加锁的访问全局变量,所以上下文的切换非常快。

 

3 进程和线程的区别:

         1 线程共享内存空间,进程是独立内存。

         2 同一个进程的线程之间可以直接交流,两个进程想要通信,必须通过一个中间代理来实现。

         3 创建新的线程很简单,创建新进程需要对其父进程进行一次克隆

         4 一个线程可以控制和操作同一进程里的其他线程,但是进程只能操作子进程。

4 装饰器

         本质是函数,作用:就是为其他函数添加附加功能。

复制代码
import functools
def itcast1(fun):
    @functools.wraps(fun)
    def inner(*args, **kwargs):
        print("itcast1 start")
        # args是元祖数据
        # kwargs是字典数据
        result = fun(*args, **kwargs) # 解包
        print("itcast1 end")
        return result
    return inner
复制代码

 

 

 

5 谈谈你对同步,异步,阻塞非阻塞理解

         同步:就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回。

         异步:发送一个请求后,不等待处理的结果,继续处理以下自己的逻辑。

         了解阻塞和非阻塞首先要知道什么情况下会发生阻塞,对于一次io访问,数据会先被拷贝到操作系统内核的缓冲区中,然后才会从操作系统内核的缓冲区拷贝到应用程序的地址空间。所以说,当一个read操作发生时,它会经历两个阶段。1 等待数据准备 2 将数据从内核拷贝到进程中。

         正因为这两个阶段,linux系统才产生了以下五种网络模式的方案:1 阻塞io,等待数据的时候会卡 2 非阻塞io 等待数据时候不卡,但数据从内核拷贝到进程中会卡。3 异步io 发送一个请求后,自己退出,不等待结果,数据完成后,直接发送给用户 4 io多路复用 直接发送多个链接,有一个数据接受成功就返回。信号驱动:我也不会。

 

6 全局解释器锁(GIL),对多线程的影响?

         GIL来源是 python 设计之初的考虑,为了数据安全所做的决定。每个 CPU 在同一时间只能执行一个线程, 在单核 CPU 下的多线程其实都只是并发,不是并行。并行是指两个或者多个事件在同一时刻发生;而并发是指两个或多个事件在同一时间间隔内发生。在 Python 多线程下,每个线程的执行方式: 1、获取 GIL 2、执行代码直到 sleep 或者是 python 虚拟机将其挂起。3、释放 GIL 。可见,某个线程想要执行,必须先拿到 GIL,我们可以把 GIL 看 作是“通行证”,并且在一个 python 进程中,GIL 只有一个。拿不到通行证的线程,就不允许进入 CPU 执行。IO 密集型代码(文件处理、网络爬虫等),多线程能够有效提升效率(开启多线程能在线程 A 等待时,自动切换到线程 B,可以不浪费 CPU 的资源,从而能提升程序执行效率),所以多线程对 IO 密集型代码比较友好。

 

7. python 中的反射?  

         python中反射的核心本质其实就是利用字符串的形式去对象(模 块)中操作(查找/获取/删除/添加)成员,一种基于字符串的事件驱动。

         hasattr(obj,str), getattr(obj,str) setattr(obj,str) delattr(obj,str)

 

8  python2 和 python3 的区别?

         Py3.X 源码文件默认使用 utf-8 编码 

         输入函数改变了,删除了 raw_input,用 input 代替:

         去除 print 语句,加入 print()函数实现相同的功能

         关键词加入 as 和 with,还有 True,False,None

         新的 super(),可以不再给 super()传参数

 

9 什么是 pep8?

         1 变量

                   常量:大写加下划线 USER_CONSTANT

                   私有变量 : 小写和一个前导下划线 _private_value

                   内置变量 : 小写,两个前导下划线和两个后置下划线 __class_

         2 函数和方法

                   总体而言应该使用,小写和下划线

私有方法 :小写和一个前导下划线 def _secrete(self):

特殊方法 :小写和两个前导下划线,两个后置下划线 def __add__(self, other):

         3 类

                   类总是使用驼峰格式命名,即所有单词首字母大写其余字母小写.

         4 模块和包

除特殊模块 __init__ 之外,模块名称都使用不带下划线的小写字母。

 

10  什么是线程安全?

         线程安全是在多线程的环境下,能够保证多个线程同时执行时程序依旧运行正 确, 而且要保证对于共享的数据可以由多个线程存取,但是同一时刻只能有一个线 程进行存取。多线程环境下解决资源竞争问题的办法是加锁来保证存取操作的唯一性。

 

11  find 和 grep?

         grep 命令是一种强大的文本搜索工具,grep 搜索内容串可以是正则表达式, 允许对文本文件进行模式查找。如果找到匹配模式, grep 打印包含模式的所有行。 find 通常用来在特定的目录下搜索符合条件的文件,也可以用来搜索特定用户 属主的文件。

 

12 什么是面向对象编程?

       面向对象编程是一种解决软件复用的设计和编程方法。 这种方法把软件系统中 相近相似的操作逻辑和操作 应用数据、状态,以类的型式描述出来,以对象实例的形式 在软件系统中复用,以达到提高软件开发效率的作用。

 

13 面向对象有那些技术? 

         类(Class): 用来描述具有相同的属性和方法的对象的集合

         类变量:类变量在整个实例化的对象中是公用的

         方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写

         实例变量:定义在方法中的变量,只作用于当前实例的类。

         继承:即一个派生类(derived class)继承基类(base class)的字段和方法

         实例化:创建一个类的实例,类的具体对象。

         方法:类中定义的函数

对象:通过类定义的数据结构实例。

 

14 静态方法和类方法?

         静态方法:需要通过修饰器@staticmethod 来进行修饰,静态方法不需要多 定义参数。 类方法:类方法是类对象所拥有的方法,需要用修饰器@classmethod 来标识 其为类方法,对于类方法,第一个参数必须是类对象,一般以 cls 作为第一个参 数(也可以用其他名称的变量作为其第一个参数),能够通过实例对象和类对象 去访问。

 

15 类属性、实例属性?

         类属性:定义在类里面但在函数外面的变量,是静态的。类对象所拥有的属性,它被 所有类对象的实例对象所共有.

实例属性:定义在__init__()方法里的变量就是实例属性,这些属性只有被创建时才会 被创建。

16  python 的多进程与多线程的运行机制是什么?有什么区别? 分别在什么情况下用?

         运行机制:进程是具有一定独立功能的程序,进程是系统进行资源分配和调度的一个独立单位 线程是进程的一个实体,是 CPU 调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。

         区别:
         多进程稳定性好,一个子进程崩溃了,不会影响主进程以及其余进程。但是缺点是创 建进程的代价非常大,因为操作系统要给每个进程分配固定的资源,并且,操作系统对进 程的总数会有一定的限制,若进程过多,操作系统调度都会存在问题,会造成假死状态。 多线程效率较高一些,但是致命的缺点是任何一个线程崩溃都可能造成整个进程的崩 溃,因为它们共享了进程的内存资源池。

使用情况:

如果代码是 IO 密集型的,多线程。 如果代码是 CPU 密集型的,多进程是更好的选择——特别是所使用的机器是多核 或多 CPU 的。

 

17 如何提高 Python 的运行效率,请说出不少于 2 种提高运行效 率的方法。

         1 使用生成器

    2 关键代码使用外部功能包:Cython、Pylnlne、PyPy、Pyrex

    3 针对循环的优化——尽量避免在循环中访问变量的属性

 

18 介绍下“消费者”和“生产者”模型。

         生产者-消费者模型是多线程同步的经典案例。此模型中生产者向缓冲区 push 数据,消 费者从缓冲区中 pull 数据。

         中缓冲区用 python 实现的 Queue 来做,这个模块是线程安全的使开发者不 用再为队列增加额外的互斥锁.

         生产者消费者模型的优点:

1、  解耦, 两者之间不直接依赖

2、  支持并发, 由于生产者与消费者是两个独立的并发体,他们之间是用缓冲区作为桥梁连接,生产者只 需要往缓冲区里丢数据,就可以继续生产下一个数据,而消费者只需要从缓冲区了拿数据 即可,这样就不会因为彼此的处理速度而发生阻塞

3、  支持忙闲不均, 如果制造数据的速度时快时慢,缓冲区的好处就体现出来了。当数据制造快的时候,消费 者来不及处理,未处理的数据可以暂时存在缓冲区中。 等生产者的制造速度慢下来,消费者再慢慢处理掉。

 

19 大数据的文件的读取

  1. 读取大于几 G 的大文件,可以利用生成器
def open_txt(file_name):
  with open(file_name,'r+') as f:
    while True:
      line = f.readline()
      if not line:
        return
      yield line.strip() #strip()去掉开头和结尾的换行符

 

 

2.对可迭代对象 file,进行迭代遍历:for line in file,会 自动地使用缓冲 IO(buffered IO)以及内存管理,而不必担心任何 大文件的问题。

 with open('filename') as file: 
    for line in file: 
        do_things(line)

    

 

posted @   Crazymagic  阅读(157)  评论(0编辑  收藏  举报
编辑推荐:
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
阅读排行:
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
点击右上角即可分享
微信分享提示

目录导航