• 面试题-python基础


    一、Python基础

    1、什么是python?使用python有什么好处?

    python是一种编程语言,它有对象、模块、线程、异常处理和自动内存管理。它简洁,简单、方便、容易扩展、有许多自带的数据结果,而且它开源

    Python是一种解释性语言,它的源代码可以直接运行,Python解释器会将源代码转换成中间语言,之后再翻译成机器码再执行

    2、可变类型与不可变类型

    可变类型:list、dict、可变集合set

    不可变类型:数字,str,tuple元组,frozenset

    内存中的那块内容(value)是否可变

    可直接在原来的地址,修改

    不可变的类型都可以被hash哈希

    3、深浅copy

    对不可变类型进行copy的话,都是深copy

    对于可变类型进行copy的话,一般都是浅copy

    浅拷贝只是增加了一个指针指向所复制的对象,共用一块内存

    深拷贝是增加一个指针并且开辟了新的内存,这个增加的指针指向这个新的内存,

    In [42]: li = [1,2,3,[4,5]]
    In [43]: li2 = copy.copy(li)
    In [44]: li3 = copy.deepcopy(li)
    
    
    In [45]: li[-1][-1] = "222"
        
    In [46]: li
    Out[46]: [1, 2, 3, [4, '222']]
    
    In [47]: li2
    Out[47]: [1, 2, 3, [4, '222']]
    
    In [48]: li3
    Out[48]: [1, 2, 3, [4, 5]]
    

    简单来说,如果有嵌套的话,浅copy只复制第一层,深copy会复制所有的

    4、range-and-xrange

        py2:
            range() 生成的是列表
            xrange() 生成的是一个生成器 
        py3:
            range() 就是一个生成器
            xrange() 没了
    

    5、闭包

    def func():
        
        def inner():
            print('aaaa')  
            
        return inner
    
    func()()  # aaaa 
    

    内部函数对外部函数作用域里变量的引用(非全局变量),则称内部函数为闭包。

    闭包的意义:返回函数对象+一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域

    6、装饰器

    调用装饰器其实是一个闭包函数,

    不修改函数的代码与修饰方式,为其他函数添加附加功能

    比如:插入日志、性能测试、事物处理、缓存、权限验证等

    # 装饰器
    import time
    def login(func):
        def inner():
            start_time = time.time()
            func()
            end_time = time.time()
            print("fun 执行时间",end_time-start_time)
        return inner
    
    @login
    def test():
        for i in range(10000):
            for j in range(10000):
                pass
        print('test函数执行')
    
    test()
    # test函数执行
    # fun 执行时间 2.0163347721099854
    

    7、生成器

    延迟操作,需要的时候才产生结果,而不是立即产生结果

    在每次调用next()的时候执行,遇到yield语句返回

    创建生成器的两种方式:

    li = [i for i in range(100)]、yield方法

    8、迭代器

    for循环的数据类型:集合数据类型+生成器

    list,tuple,dict,set,str + generator

    不是一次性把数据加载到内存,而是被next()函数调用,不断返回下一个数据

    9、*args与**kwargs

    *args:位置参数 ('alex',18)

    **kwargs:关键字参数 {'name'='alex','age'=18} 关键字参数一定要放在最后面

    二、面向对象

    1、经典类、新式类

    经典类:深度优先,python2中

    新式类:广度优先,Python3中

    2、继承、多态、封装

    (1)继承:类与类之间关系,Cat类是动物类,解决代码重用问题

    重用 父类的属性与方法

    def __init__(self, name, life_value, aggresivity, weapon):
            super().__init__(name, life_value, aggresivity,)        # python3格式
            self.weapon = weapon
    
     def attack(self, enemy):
           super().attack(enemy)
    

    (2)多态:同一类事物多种形态

    一个接口,多种形态

    不应关注对象的类型本身,而是它如何使用的

    鸭子类型:如果看起来像、叫声像而且走起路来像鸭子,那么它就是鸭子’

    (3)封装

    私有化的属性,私有化的方法,封装起来,外部无法调用 双下划线__foo

    3、classmethod,staticmethod,property

    (1)property:特性 (统一访问 原则)

        @property
        def bmi(self):
            return self.weight / (self.height ** 2)
    

    把类的方法转换为属性,直接 alex.bmi 调用

    (2)staticmethod 静态方法 (普通函数 ) 绑定到对象上

    类内的函数实例化---> 普通函数 。 (类和对象都可以使用)

        @classmethod
        def from_conf(cls):
            obj = settings.name,
            return obj
    

    (3)classmethod 类方法 (def foo(cls)) 绑定到类上

    将cls 类本身当做参数传入,直接用类来调用函数,而不用借助类实例

    优雅地实现某个类的实例的构造

    4、 new.init区别,如何实现单例模式

    创建一个新实例时调用new new()在 init()之前被调用

    初始化一个实例时调用init

    单例模式设计的类只能实例化1个对象

    # 方式1 python模板自带单例模式
    # admin.py
    
    class Admin(object):
        def register(self):
            pass
    
    site = Admin()
    
    # test.py
    from admin import site
    site.register()
    
    # 方式2  __new__  _instance
    class Single(object):
        _instance = None
        def __new__(cls,*args,**kwargs):
            if not cls._instance:
                cls._instance = super(Single,cls).__new__(cls,*args,**kwargs)
                
            return cls._instance
    

    5、反射

    “字符串”形式,操作对象的相关属性或方法。

    hasattr, getattr, setattr, delattr

    ret = getattr(obj,'get_file')()       # 反射  obj是实例对象,name是方法 
    

    三、并发

    1、线程、进程的区别

    (1)进程:程序的运行过程, os 资源调度、分配的基本单位 os的并发

    (2)线程:进程的实体, cpu 调度、分派的基本单位 进程内部的并发

    区别

    1、进程有独立的内存空间, 线程 共享 本进程 的内存空间

    2、进程有独立的系统资源 ,线程只有(程序计数器,一组寄存器,栈) 共享本进程的资源(内存,I/O,cpu)

    3、独立性:进程崩溃,不会影响其他的(健壮) 线程崩溃,本进程的全部线程死掉

    4、开销:进程切换与创建 开销大于 线程的

    5、线程不能独立执行 进程可以

    联系

    都可并发、一个进程由1or多个线程 组成、一个进程中的所有线程共享该进程全部资源
    

    2、协程、GIL

    GIL:全局解释器锁(cpython解释器), 同一时刻,在cpu只能有一个线程执行

    协程:轻量级的线程,用户控制调度的

    单线程下(的并发), 遇到I/O阻塞,多个任务,自动切换

    3、进程同步方式

    1、Event事件 。 通知操作

    2、互斥量。 加锁

    3、信号量。 生产者消费者模型 阻塞队列Queue

    4、临界区 。保护区域

    同步问题:生产者消费者模型,作者读者问题,哲学家进餐问题

    4、通信方式

    管道,系统IPC(消息队列,信号量,信号,共享内存),套接字,远程过程调用rpc

    5、死锁

    多个进程运行,争夺资源,一种僵局;没有外力,进程,无法继续执行

    导致死锁的原因:循环等待、不可抢占、占有且等待、互斥

    死锁处理:

    1、预防 :破坏4个条件

    2、避免:银行家算法

    3、检测:算法检测,清除死锁

    4、解除: 检测到,撤销进程or剥夺资源

    6、select、poll和epoll (I/O多路复用)

    可以监视多个描述符

    一个描述符就绪,通知应用程序,执行读or写操作

    (1)select :

    把文件描述符 fd 集合maxSize=1024,用户态copy到内核态 开销大,在内核,遍历所有fd

    (2)poll:

    改善了连接数,不断轮询,fd集合 每次都copy到内核态

    (3)epoll:

    linux下的多路复用I/O接口, 只copy一次,只告知 ,刚变为就绪状态的fd

    四、mysql数据库

    1、索引

    B+数:二叉树-->平衡二叉树-->B数

    一个排序好,数据结构 (协助快速查询data) 范围查询

    create index ix_age on t1(age);
    create index 索引名1,索引名2 on 表名('字段1','字段2')
    

    (1)什么时候用?

    经常 select查询、表记录超多

    经常需要搜索的列、主键列、连接的列(外键)、范围查找 age in [20,40]、排序的列 salary、where上的列

    (2)什么时候不用?

    经常update,delete,insert 表记录少

    不经常使用的列 addr,数据值很少的列 blog,文本,image,bit 修改>查询的

    2、存储过程

    相当于 函数,封装了,一系列,可执行的sql语句,存放在mysql中

    直接调用它的名称

    create procedure p1()
    BEGIN
        select * from blog;
        INSERT into blog(name,sub_time) values("xxx",now());
    END
    

    优点:网络传输量小,程序与slq解耦

    缺点:程序猿拓展功能不方便

    3、数据库引擎

    INNODB 支持事务,外键,行锁, 查表总行数,全表扫描

    MYISAM不支持事务,不支持外键,表锁(插入data,锁定这个表),查表总行数,不需要全表扫描

    4、redis

    key-value数据库 ,经常用的data放在redis

    性能极高,支持多种数据类型 ,放在内存中 (必要时可以写入硬盘)

    五、网络

    1、http常用的状态码

    200:请求成功 OK

    202:服务器接受请求,尚未处理

    302:重定向

    304  :上次的文档,已被缓存, 还可继续使用

    400:客户端请求语法or参数错误

    403:服务器收到请求,拒绝提供服务,找不到cookie

    404:客户端请求的资源url不存在

    500: 服务器的程序出现错误

    503:服务器当前时间不能处理客户端的请求,一段时间后恢复

    2、HTTP请求方式

    HTTP1.0 GET/HEAD/POST

    HTTP1.1 PUT/DELETE/CONNECT/OPTIONS/TRACE

    3.GET/POST区别

    (1)get提交的数据放在url后 /?name=alex&age=18 http请求头

         post的数据放在http报请求体
    

    (2)GET的数据大小有限制,POST没有限制

    (3)GET方式会带来安全问题,在url出现信息,可能获得username password

    (4)在服务端 获取请求数据方式不同

    4、http请求头,请求体

    协议版本,状态码,状态码原因 HTTP /1.1 200 OK

    Cookie:

    Content-Language

    Content-Type 文本类型

    Content-Length 请求体长度

    User-Agent: 浏览器的身份标识,类型,手机端or电脑端

    Date:时间

    请求体

    5、TCP/UDP区别 (运输层)

    1、TCP 传输控制协议,面向连接的,可靠的,数据流传输 ,注重data安全性,传输慢,面向字节流

    2、UDP用户数据报文协议,非面向连接的,不可靠,数据流传输, data传输快,安全性一般,面向报文

    python部分

    4、深浅拷贝

    浅拷贝只是增加了一个指针指向一个存在的地址,
    深拷贝是增加一个指针并且开辟了新的内存,这个增加的指针指向这个新的内存,
    简单地说,浅拷贝只拷贝一层(如果有嵌套),深拷贝拷贝所有层。

    In [42]: li = [1,2,3,[4,5]]
    In [43]: li2 = copy.copy(li)
    In [44]: li3 = copy.deepcopy(li)
    
    
    In [45]: li[-1][-1] = "222"
        
    In [46]: li
    Out[46]: [1, 2, 3, [4, '222']]
    
    In [47]: li2
    Out[47]: [1, 2, 3, [4, '222']]
    
    In [48]: li3
    Out[48]: [1, 2, 3, [4, 5]]
    
    7、闭包
    内部函数对外部函数作用域里变量的引用(非全局变量),则称内部函数为闭包。

    闭包的意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域

    def func():
        
        def inner():
            print('aaaa')  
            
        return inner
    
    func()()  # aaaa 
    
    6、装饰器

    调用装饰器其实是一个闭包函数,为其他函数添加附加功能,不修改被修改的源代码和不修改被修饰的方式,装饰器的返回值也是一个函数对象。
    比如:插入日志、性能测试、事物处理、缓存、权限验证等,有了装饰器,就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。

    # 装饰器
    import time
    def login(func):
        def inner():
            start_time = time.time()
            func()
            end_time = time.time()
            print("fun 执行时间",end_time-start_time)
        return inner
    
    @login
    def test():
        for i in range(10000):
            for j in range(10000):
                pass
        print('test函数执行')
    
    test()
    # test函数执行
    # fun 执行时间 2.0163347721099854
    
    1、什么是python?使用python有什么好处?

    python是一种编程语言,它有对象、模块、线程、异常处理和自动内存管理。它简洁,简单、方便、容易扩展、有许多自带的数据结果,而且它开源
    Python是一种解释性语言,它的源代码可以直接运行,Python解释器会将源代码转换成中间语言,之后再翻译成机器码再执行

    3、数组和元祖之间的区别是什么?

    数组和元祖之间的区别:数组内容可以被修改,而元祖内容是只读的,不可被修改的,另外元祖可以被哈希,比如作为字典的key

    5、os与sys区别:

    os是模块负责程序与操作系统的交互,提供了访问操作系统底层的接口
    sys模块是负责程序与python解释器的交互,提供了一系列的函数和变量,用于操控Python时运行的环境

    15、range-and-xrange
        py2:
            range() 生成的是列表
            xrange() 生成的是一个生成器 
        py3:
            range() 就是一个生成器
            xrange() 没了
    
    21、什么是pickling和unpickling?

    Pickle模块读入任何python对象,将它们转换成字符串,然后使用dump函数将其转储到一个文件中——这个过程叫做pickling
    反之从存储的字符串文件中提取原始python对象的过程,叫做unpickling

    8、迭代器与生成器

    生成器:Python使用生成器对延迟操作提供了支持。所谓延迟操作,是指在需要的时候才产生结果,而不是立即产生结果。这也是生成器的主要好处。

    这里,最难理解的就是generator和函数的执行流程不一样。
    函数是顺序执行,遇到return语句或者最后一行函数语句就返回。generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次被next()调用时从上次返回的yield语句处继续执行。

    迭代器

    可以直接作用于for循环的数据类型:

    • 一类是集合数据类型,如listtupledictsetstr等;
    • 一类是generator,包括生成器和带yield的 generator function。
      不是一次性把数据加载到内存,而是被next()函数调用,不断返回下一个数据
    9、classmethod,staticmethod,property

    类方法:将类的函数转换成类方法,函数上装饰@classmethod会将函数的自动传值参数改成cls
    静态方法:此方法相当于给类扩展一个功能,将类内的函数实例化,给类或对象使用,此时类内的函数就是普通函数,不管是类还是实例化的对象都可以使用
    实例化:类的实例化就会产生一个实例(对象),可以理解为类()把虚拟的东西实例化,得到具体存在的值

    10、 new.init区别,如何实现单例模式,有什么优点

    __new__是一个静态方法,__init__是一个实例方法
    __new__返回一个创建的实例,init__什么都不返回
    new__返回一个cls的实例时后面的__init__才能被调用
    当创建一个新实例时调用__new
    ,初始化一个实例时调用__init

     _new_()在 _init_()之前被调用,用于生成实例对象。利用这个方法和类的属性的特点可以实现设计模式的单例模式。
     单例模式是指创建唯一对象,单例模式设计的类只能实例,实例化1个对象
    
                       class Singleton(object):
                            __instance=None
                            def __init__(self):
                                pass
                            def __new__(cls, *args, **kwargs):
                                if Singleton.__instance is None:
                                    Singleton.__instance=object.__new__(cls,*args,**kwargs)
                                return Singleton.__instance
    
    2. python面向对象中的反射:
    通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)
    11、多进程,多线程,协程,GIL

    GIL:全局解释器锁,是锁在cpython解释器上,导致同一时刻,同一进程只能有一个线程被执行
    多进程:多进程模块multiprocessing来实现,cpu密集型,IO计算型可以用多进程
    多线程:多线程模块threading来实现,IO密集型,多线程可以提高效率
    协程:依赖于geenlet,对于多线程应用。cpu通过切片的方式来切换线程间的执行,遇到IO操作自动切换,线程切换时需要耗时,
    而协成好处没有切换的消耗,没有锁定概念。
    进程:是资源管理单位,进行是相互独立的,实现并发和并发
    线程:是最小的执行单位,线程的出现为了降低上下文切换的消耗,提供系统的并发性

    12、IO多路复用/异步非阻塞

    IO多路复用:通过一种机制,可以监听多个描述符 select/poll/epoll
    select:连接数受限,查找配对速度慢,数据由内核拷贝到用户态
    poll:改善了连接数,但是还是查找配对速度慢,数据由内核拷贝到用户态
    epoll:epoll是linux下多路复用IO接口,是select/poll的增强版,它能显著提高程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率
    异步非阻塞:异步体现在回调上,回调就是有消息返回时告知一声儿进程进行处理。非阻塞就是不等待,不需要进程等待下去,
    继续执行其他操作,不管其他进程的状态。

    14、PEP8规范,规范的好处是什么?

    1.缩进:4个空实现缩进,尽量不使用Tab
    2.行:没行最大长度不超过79,换行可以使用反斜杠
    3.命名规范:
    4.注释规范:

    16、with上下文机制原理

    enter_和_exit,上下文管理协议,即with语句,为了让一个对象兼容with语句,必须在这个对象类中声明_enter_和_exit_方法,
    使用with语句的目的就是把代码块放入with中执行,with结束后,自动完成清理工作,无须收到干预

    17、经典类、新式类

    经典类遵循:深度优先,python2中
    新式类遵循:广度优先,Python3中

    25、Python都有哪些自带的数据结构?
    可变:列表  字典
    不可变: 数字  字符串  元祖
    
    26、命名空间?

    在python中,所有的名字都存在于一个空间中,它们在改空间中存在和被操作——这就是命名空间,它就好像一个盒子,在每个变量名字都对应装着一个对象,
    当查询变量的时候,会从该盒子里面寻找相应的对象

    28、*args与**kwargs

    *args代表位置参数,它会接收任意多个参数并把这些参数作为元祖传递给函数。
    **kwargs代表的关键字参数,返回的是字典,位置参数一定要放在关键字前面

    7.索引B+树

    B+树(数据结构,平衡树,根节点,子节点,数据) 索引能够让数据库查询数据的速度上升,而使写入数据的速度下降, 因为平衡树这个结构必须一直维持在一个正确的状态, 增删改数据都会改变平衡树各节点中的索引数据内容,破坏树结构, 因此,在每次数据改变时, DBMS必须去重新梳理树(索引)的结构以确保它的正确,这会带来不小的性能开销, 也就是为什么索引会给查询以外的操作带来副作用的原因。

    8.哈希表

    (Hash Table,又称为散列表),是一种线性表的存储结构。通过把每个对象的关键字k作为自变量,通过一个哈希函数h(k),将k映射到下标h(k)处,并将该对象存储在这个位置。

    例如:数据集合{1,6,7,9},假设存在哈希函数h(x)使得h(1) = 0, h(6) = 2, h(7) = 4, h(9) = 5,那么这个哈希表被存储为[1,None, 6, None, 7, 9]。
    当我们查找元素6所在的位置时,通过哈希函数h(x)获得该元素所在的下标(h(6) = 2),因此在2位置即可找到该元素。
    

  • 相关阅读:
    JAVA,统计字符串里面每个字符出现的次数
    JAVA,遍历HashMap的2种方式,keySet方法和entrySet对象
    JAVA,Map接口常用方法
    JAVA,Collection集合常用API和集合特点
    object类常用方法
    [Algorithm] 双指针应用
    [CV]计算机视觉中值变换、拉普拉斯算子、傅里叶变换
    [CNBlogs]使用Typora和MetaWeblog改善博客园书写体验
    [C#] 动态编程表达式树实现NPOI.IROW快速映射优化
    [CV] 计算机视觉像素位变换(反转变换、对数变换,伽马变换,直方图均衡化)
  • 原文地址:https://www.cnblogs.com/venicid/p/9669638.html
Copyright © 2020-2023  润新知