返回顶部

基础篇--【python】面试题汇总

1.尽可能多的列举PEP8规范有哪些?

  1.   不要在行尾加分号,也不要用分号将两条命令放在一行
  2.   每行不超过80个字符
  3.   不要使用反斜杠连接行
  4.   在注释中,如果有必要,将长的url放在一行
  5.   除非用于实现行连接,否则不要在返回语句或条件语句中使用括号
  6.   用4个空格代替代码缩进,不要使用TAB
  7.   顶级定义之间空2行,方法定义之间空1行

2.ascii,unicode,utf-8,gbk的区别

  ascii 8位 一个字节

  unicode A:32位,四个字节  中文:32位,四个字节

  utf-8 A:8位,一个字节    中文:16位,两个字节

  gbk A:8位,一个字节   中文:16位,两个字节

  区别:

    1.各个编码之间的二进制是不能互相识别的

    2.文件的存储,传输,不能是unicode,只能是utf-8,gbk,ascii

  转换:

    encode str > bytes 编码

    decode bytes > str 解码

3.python递归的最大层数是多少以及如何修改

  python默认递归最大数为1000,用于防止无限递归造成内存溢出奔溃

  修改方法:

    import sys

    sys.setrecursionlimit(1500)  

4.字节码和机器码的区别

  字节码是一种中间状态的二进制代码,需要直译器转译后才能成为机器码

5.三元运算符是什么

  三元运算符就是在赋值变量的时候,可以直接加判断

  res = a if a > b else b

6.列举python2和python3的区别

  print : 2print语句,3print函数

  输入函数:2 input_raw() ,3 input()

  super(): 2 必须显示的在参数中写上基类,3直接无参数调用即可

  没有了int和long的区别

  编码:2 默认ascii,3默认utf-8

  字符串:

    2.unicode表示字符串序列,str表示字节序列

    3.str表示字符串序列,byte类型表示字节序列

  true和false:

    2.可以赋值和操作

    3.不可变

  迭代器:

    2.当中许多返回列表的方法,如range,字典对象的dict.keys(),dict.values()方法,map,filter,zip:并且迭代器必须实现next方法

    3.将返回列表的方法改为了返回迭代器对象,内置了__next__,不用特意去实现next

 

7.用一行代码实现数值交换

  a,b = b,a

8.xrange和range的区别

  range和xrange都是在循环中使用,输出结果一样

  range返回一个list对象,xrange返回一个生成器对象

  xrange每次调用返回其中的一个值,内存占用少,性能好

9.字符串,列表,元组,字典各自常用的方法

string:
    去掉空格和特殊符号:
    name1 = name.strip() #去掉两边空格
    name2 = name.lstrip() #去掉左边空格
    name3 = name.rstrip() #去掉右边空格
    搜索和替换:
    name.count("e") #查找某个字符在字符串中出现的次数
    name.capitalize() #首字母大写
    name.center(100,"-") #把字符串放中间,两边用-补齐到100
    name.find("a") #找到这个字符返回下标,存在多个返回第一个,不存在返回-1
    name.index("a") #找到这个字符返回下标,存在多个返回第一个,不存在报错
    print(name.replace(name,"123"))  #字符串的替换
    name.replace("abc","123") #返回一个替换后的字符串
    验证和替换函数:
    name.startswith("abc") #是否以abc开头
    name.endswith("abc") #是否以abc结尾
    name.isalnum() #是否全十字母和数字,并且至少包含一个字符
    name.isalpha() #是否全是字母,并且至少包含一个字符
    name.isdigit() #是否全是数字,并且至少包含一个字符
    name.isspace() #是否全是空白字符,并且至少包含一个支付
    name.islower() #是否全是小写
    name.isupper() #是否全是大写
    name.istitle() #是否首字母大写
    字符串的分割:
    name.split('') #默认按照空格进行分割,从前往后
    name.rsplit() #从后往前分割

    连接字符串:
    '.'.join(name) #用.号将一个可迭代的序列拼接起来

    切片:

    name1 = name[0:3] #截取第一位到第三位的字符
    name2 = name[:] #截取全部字符
    name3 = name[6:] #截取第6个字符到结尾
    name4 = name[:-3] #截取从开头到最后一个字符之前
    name5 = name[-1] #截取最后一个字符
    name6 = name[::-1] #创造一个与原字符串顺序相反的字符串
    name7 = name[:-5:-1] #逆序截取

列表:
    列表的特性:
    有序集合,通过偏移来索引,从而读取数据,支持嵌套,可变类型
    
    创建列表:
    list1 = ["1","2","3","4"] #方法1
    list2 = list("1234") #方法2

    添加元素:
    末尾追加:
        list1.append(5)
    指定位置前面插入:
        list1.insert(2,6) #下标为2的前面插入6
    追加一个列表:
        list1.extend([7,8,9])

    遍历列表:
    直接遍历:
        for i in list1:
            print(i)
    带索引遍历:
        for index,i in enumerate(list1):
            print(i,index)

    通过下标取值:
    print(list1[2])

    删除元素:
    list1.remove() #参数object,删除靠前的重复元素,无重复返回None
    list1.pop() #可选参数 index,删除指定位置的元素,默认为最后一个元素
    del list1[1] #删除列表或者指定元素或者切片,删除后无法访问

    排序和反转代码:
    list1.reverse() #反转列表
    list1.sort() #排序

字典:
    字典是无序的可变序列
    
    创建:
    空字典:
        dict1 = {} 
        dict2 = dict()
    值为None的字典:
        dict3 = dict.fromkeys(['a','b','c'])  ==> {'a':None,'b':None,'c':None}
    通过zip函数构建字典
        dict4 = dict(zip(keyslist,valueslist))
    通过赋值表达式元组构造字典
        dict5 = dict(name='bob',age=22) ==> {'name':'bob','age':22}
    成员关系:
    字典的成员关系只判断key,与value无关
    列出所有的健,值,键值对:
    dict6.keys() #键 返回的是可迭代对象
    dict7.values() #值 返回的是可迭代对象
    dict8.items() #键值对 返回的是可迭代对象
    拷贝一个字典的副本:
     dict9 = dict8.copy() #浅拷贝
     dict10 = dict8.deepcopy() #深拷贝
    根据键获取值,默认值default
          dict11 = dict12.get(key,default)
    合并更新字典
          dict13.updat(dict12)
    删除字典
          d.pop(key)
    新增或者修改键对应的值
          D[2] = value #如果存在则修改,不存在则创建
    获取字典键的列表,值的列表
          list(D.keys())
          list(D.values())
    字典推导式
          D = [x:x**2 for x in range(10) if x %2 == 0]
    字典使用事项
          序列运算无效,字典是映射机制
          对新索引的赋值会添加新的键值对
          键不一定总是字符串,但总是不可变对象

元组:
    概述:
        任意对象的有序集合,可以通过序列取值
        元组不可变的序列的操作类型
        固定长度,异构,嵌套(元组里也可以包含元组)
    创建:
        空元组
            t1 = ()
            t2 = tuple()
        单个元素要加,
            x = (40,) ==>一个元组,具有一个元素的值是40

        多元素元组的表达方式
            t = (1,2,3) 
            t1 = 1,2,3 #括号可以省略

        用一个可迭代对象生产元组
            t = tuple('abc')

        元组的访问
            t[i] t[i][j]

        合并和重复
            t1 + t2
            t1 * 3

        迭代和成员关系
            for x in T:
                print(x)
            'spam' in T

        对元组进行排序
            对元组排序,通常先得将它转换为列表并使得它成为一个可变对象,或者使用sorted方法,它接收任何序列对象

            T = ('c','a','b','d')
            tmp = list(T)
            tmp.sort() ==> ['a','b','c','d']

            T = tunple(tmp)
            sorted(T)

        为何有了列表还要用元组
            元组可以看成是简单得对象组合,而列表是随着时间而改变得数据集合
            元组得不可变性提供了某种完整性,这样可以确保元组不会被另外一个引用来修改
            元组类似其他语言中的常数声明

集合
    创建:
        a = set()
        b = set(iterable) #用可迭代对象创建一个集合
    集合的运算:
            & 生成两个集合的交集 s3 = s1 & s2
            | 生成两个集合的并集 s3 = s1 | s2
            - 生成两个集合的补集 s3 = s1 - s2
            ^ 对称补集 s3 = s1 ^ s2 (只能属于s1或者s2,也就是去除掉s1和s2重合的部分)

10.lambda表达式格式以及应用场景?    

  举例:
        from functools import reduce
        add = lambda x,y:x+y
        print(add(1,2)) # 输出3

    与map和用,遍历序列,对序列中每个元素进行操作,获取最终的新序列
        x = [11,22,33]
        print(list(map(lambda x:x=100,x))) #[111,122,133]

    与filter和用,对序列中的元素进行筛选,最终获取符合条件的序列
        x2 = [11,22,33]
        print(list(filter(lambda x:x>20,x)))

    与reduce和用,对序列内所有元素进行累计操作
        x3 = [1,2,3,4]
        print(reduce(lambda x1,x2:x1+x2,x3))

11.*arg和**kwarg作用?    

  *arg和**kwarg都是用来传不固定个数的参数到函数中的    

  *arg :可以理解为只有一列的元组,长度不固定
     **kwarg:可以理解为字典,长度不固定。

    二者可以单独使用,或者组合使用,一起使用的时候,*arg要放在**kwarg之前。

12.is和==的区别    

  python中对象包含的三个基本要素,分别是:
          id(身份标识)
          type(数据类型)
          value(值)
      对象之间判断是否相等就需要用到is 或者 ==:

        is 判断两个对象的id值是否相等,即两个对象是否指向同一个内存地址
        == 判断两个对象的值是否相等

13.Python的赋值,深浅拷贝以及应用场景?

    import copy
    浅拷贝:copy.copy()
    深拷贝:copy.deepcopy()
    对于数字和字符串而言,赋值,深拷贝和浅拷贝无意义,因为其始终指向同一个内存地址。
    赋值:简单的拷贝对象的引用,两个对象的id相同
    浅拷贝指的是创建一个新的对象,仅仅拷贝数据集合的第一层数据,在内存中共享子对象
    深拷贝指的是创建一个新的组合对象,与原对象完全无关,真正独立。

14.Python垃圾回收机制?

    python垃圾回收算法GC算法,分为以下三点:
        引用计数/标记-清除/分代回收

        引用计数
            对象在被方法引用的时候会自动计数加1,当引用该对象的对象被删除的时候,那么该对象的引用计数就会减少,一直到它的引用计数变为0,垃圾回收机制就会自动回收。

            优点:
                简单实用
            缺点:
                维护性高,需要占用额外的资源
                不能解决循环引用的问题

                循环引用:两个列表相互引用

        标记-清除
            标记-清除就是用来解决循环引用的问题的。
            未来追踪容器对象,需要每个容器对象维护两个额外的指针,root链表和unreachable链表。

            因为unreachable可能存在被root链表引用的可能,所以要在标记过程中发现并将其从unreachable链表中转移到root链表中,然后剩下的才做真正的回收。

        分代回收

            理论上讲,创建量应该与释放数量相等,但是如果存在循环引用,创建量就会大于释放量,如果这个差值超出了GC的阈值,那么分代回收机制就会启动。
            分代回收将对象分为三代:
                0代表幼年对象
                1代表青年对象
                2代表老年对象

            如果在第0代的gc垃圾回收中存活下来,就会进入第1代,第2代同理;
            然后如果在上一次检查之后,第N代垃圾回收次数大于第N+1代,那么第N+1代就会做垃圾回收检查。

15.一行代码实现9*9乘法表

    print ('\n'.join([' '.join(['%s*%s=%-2s' % (y,x,x*y) for y in range(1,x+1)]) for x in range(1,10)]))

16.列举常见的内置函数?

    反射相关,总共4个
        hasattr 根据字符串的形式 , 去判断对象中是否有成员
        getattr 根据字符串的形式,去对象中找成员
        setattr 根据字符串的形式 , 动态的设置一个成员(在内存中)
        delattr 用于删除属性
            delattr(x, 'foobar') 相等于 del x.foobar
    基础数据类型相关,总共38个
        bool,int,float,complex(复数),bin(整型转换为二进制),oct(整型转换为八进制),hex(整型转换为十六进制),abs(求绝对值),divmod(除,余数),round(值,小数后几位),pow(幂运算),sum,max,min,list,tuple,reversed,slice,str,format,bytes,bytearry,memoryview,ord,chr,ascill,repr,dict,set(),frozenset,len,sorted,enumerate,all,any,zip,filter,map
    作用域相关
        locals 获取执行本方法所在命名空间内的局部变量的字典
        globals 获取全局变量的字典

    面向对象相关
        type 元类,类的最高层
        object
        classmethod  类方法,用来修改类变量
        staticmethod 类方法,用来处理一些和操作类无关的事
        propery    可以像调用一个变量一样调用一个方法
        vars
        super    在多继承中,可以保证顶层父类只被调用一次 ,用 _ _mro_ _ 查看多继承规律时,遵循深度优先原则
        issubclass    检查第一个参数是否是第二个参数的子子孙孙类  
        isinstance    检查第一个参数(对象) 是否是第二个参数(类及父类)的实例.
    迭代/生成器相关
        next
        iter
        range    range 是一个生成器,他只用来存储数据的生成方式,而不直接存储数据

    其他
        eval    将字符串类型的代码执行并返回结果
        exec    将自字符串类型的代码执行
        compile
        input
        print
        id
        hash
        open
        __import__
        help
        callable     检测一个对象能否被调用
        dir 查看内置属性和方法

17.如何安装第三方模块?以及用过哪些第三方模块?

    pip install django  #通过pip安装
    pip install -i https://pypi.douban.com/simple django  #通过豆瓣源加速安装
    python setup.py build # 源码下载解压
    python setup.py install

    #常用第三方库
    pillow #图像相关的处理库
    Scrapy # 一个快速,高级的屏幕抓取以及web爬虫框架
    requests #一个关于http请求的优秀开源库
    beautifulsoup # xml和html的解析库,比较慢,效率很低

18.re的match和search区别?

    match()函数只检测RE是不是在string的开始位置匹配,search()会扫描整个string查找匹配;

19.什么是正则的贪婪匹配?

    总是尝试匹配尽可能多的字符,对应格式:xx*xx

20.def func(a,b=[]) 这种写法有什么坑?

    函数的第二个默认参数是一个list,当第一次指向的时候实例化了一个list,第二次执行还是用第一次执行的时候实例化的地址存储。,默认参数应该设置为None

posted @ 2020-04-08 15:13  Will_D_Zhang  阅读(987)  评论(0编辑  收藏  举报