• Python面试题基础部分(附答案)


    必答题

    1,简述列举了解的编程语言及语言间的区别?

    Python        解释型语言,代码简洁,易懂
    C语言           编译型语言,底层语言
    c++            编译型语言,在C语言基础上加了面向对象
    Java        混合型语言,可拓展性高
    Golang        编译型语言,强类型,代码规范,高并发
    
    语言特点: 灵活简洁,语言优美 可读性强,
    
    语言类型:
         解释型:逐行转化,运行效率低,性能差,开发效率高。兼容性好,跨平台
         编译型 :一次性编译成二进制文件,执行效率高,兼容性差,
         动态语言:不用声明变量的数据类型(脚本类语言)
         静态语言:需要声明变量的数据类型
    
    第三方库:python定位是任其发展,开源库很多,应用领域广

    2,列举Python2和Python3的区别?

    python2只更新支持到2020年
    print:2不加括号,3加括号
    input:2中用户输入解析为int类型,raw_input为字符串类型,3直接是字符串类型
    range:2是列表,xrange是可迭代对象;3是可迭代对象
    继承关系:2是新式类+经典类;3是新式类
    数字表示:2,int和long(长整形,超出2**63-1,数字末尾有一个L);3所有整型都是int

    3,看代码写结果

    v1 = 1 or 2
    
    v2 = 3 and 3 or 9 and 0
    # v1 = 1
    # v2 = 7
    # 逻辑运算符优先级 () > not > and > or
    # 逻辑短路
    and 全真则真,一假则假
    or  一真则真,全假则假
    
    True or 表达式  => True  (单个运算符和多个运算符的情况,都可以直接判定结果)
    False and 表达式 => False(单个运算符的时候可以)
    
    # 布尔值为假的十种情况: bool() => False
        0,0.0,False,0j,'',[],(),set(),{},None
    详解

    4,以下的值有什么不同?

    v1 = [1,2,3]
    v2 = [(1),(2),(3)]
    v3 = [(1,),(2,),(3,)]
    
    """
    # 逗号才是区分是否是元组的标识符
    v1 = [1,2,3] # 列表[int , int , int]
    v2 = [(89),(2.12),("abc")] # [int , float , str]
    v3 = [(1,),(2,),(3,)] # [tuple,tuple,tuple,tuple]
    res = () # 表达空元组
    """

    5,用一行代码实现数值交换。

    a = 1
    b = 2
    
    
    a,b = b,a
    # 通用
    tmp = a
    a = b
    b = tmp

    6,Python中单引号、双引号、三引号的区别?

    单双引号没有区别,三引号可以支持跨行
    在互相嵌套时需注意:里外不能使用相同的引号

    7,is和==的区别?

    is 是判断内存地址是否一致
    == 是判断两个对象的值是否相等

    8,python里如何实现tuple和list的转化?

    list(数据) tuple(数据)

    9,如何实现字符串 st='爱吃大西瓜'的反转?

    st = st[::-1]

    10,两个set如何获取交集、并集、差集?

    交集 &
    intersection
    差集 -
    difference
    并集 |
    union
    对称差集 ^
    symmetric_difference

    11,那些情况下, y != x - (x-y)会成立?

    非空集合且不为子父关系的两个集合

    12,Python中如何拷贝一个对象?

    # copy模块
    [:]
    import copy
    copy.copy()    # 浅拷贝
    copy.deepcopy() # 深拷贝

    13,简述 赋值、浅拷贝、深拷贝的区别?

    赋值:将变量和值在内存中形成映射指向关系
    浅拷贝:只拷贝第一层元素地址copy.copy
    深拷贝:为所有层级的元素都单独开辟新空间 copy.deepcopy() (地址:原不可变数据只是暂时的指向,可变的数据独立开辟新空间)
    
    可变数据: list set dict
    不可变数据: int float bool complex str tuple

    14,pass的作用?

    pass  占位符  与  ...的用法一样

    15,阅读代码写结果:

    import copy
    a = [1,2,4,5,['b','c']]
    b = a
    c = copy.copy(a)
    d = copy.deepcopy(a)
    a.append(5)
    a[4].append('d')
    print(b)
    # [1,2,4,5,['b','c','d'],5]
    print(c)
    # [1,2,4,5,['b','c','d']]
    print(a)
    # [1,2,4,5,['b','c','d'],5]

    16,用Python实现9 * 9 乘法表。

    # while
    i = 1
    while i<=9:
        # 这个位置写代码
        j = 1
        while j<= i:
            # "谁"*"谁"="谁"
            print("%d*%d=%2d" % (i,j,i*j),end=" ")
            j+=1
            
        # 打印换行
        print()    
        i+=1
    
    # for
    for i in range(1, 10):
        for x in range(1, i + 1):
            print(f"{i} * {x} = {i * x}",end=" ")
        print("")

    17,用Python显示一个斐波那契数列。

    # 1 1 2 3 5 8 13 21 ...
    # 方法一
    lst = [1,1]
    for i in range(10):
        lst.append(lst[-1] + lst[-2])
    print(lst)
    
    # 方法二
    a,b = 0,1
    for i in range(10):
        print(b)
        a,b = b,a+b
    
    # 方法三
    def fib(n):
        if n <= 2:
            return 1
        # 上一个值 + 上上个值
        return fib(n-1) + fib(n-2)
    
    print(fib(6))

    18,如何删除列表中重复的值?

    list(set(list))

    19,一个大小为100G的文件etl_log.txt, 要读取文件中的内容, 写出具体过程代码?

    with open(r'etl_log.txt','r',enconding='utf-8') as f:
        for i in f:
            info = f.readlines()
            print(info)
    
    fp = open("文件名","模式","编码集")
    """
    fp 是迭代器
    from collections import Iterator,Iterable
    
    # 在遍历fp时,文件按照一行一行进行读取;
    for i in fp:
        code ... 
    
    """

    20,a = dict(zip(("a","b","c","d","e"),(1,2,3,4,5))) 请问a是什么?

    a为字典
    强转字典的条件:等长的二级容器,配合强转字典的两个函数 zip , enumerate
    # zip  拉链
    a = dict( zip( ("a","b") , [1,2] ) )
    print(a)
    # enumerate  枚举
    a = dict( enumerate( ["a","b"] ))
    a = dict( enumerate( ["a","b"] ,start = 10 ))
    print(a)
    详解

    21,lambda关键字的作用?

    lambda 匿名函数 : 用一句话表达只有返回值的无名函数
    lambda 参数 : 返回值

    22,*arg和**kwarg作用?

    *args 接收多余的位置参数
    **kwargs 接收多余的关键字参数

    23,如何在函数中设置一个全局变量 ?

    global  有该全局变量,修改当前变量,没有改全局变量,定义一个全局变量;    
    """
    def func():
        global a
        a = 90
    func()
    print(a)
    """

    24,filter、map、reduce的作用?

    三目(元)运算符  True   if 条件表达式 else False
    
    filter => 过滤数据
    iterable : 可迭代对象(range ,容器类型数据 , 迭代器)
    filter(func,iterable)  => 返回迭代器
    
    lst = [1,2,3,4,5]
    it = filter(lambda x : True   if x % 2 == 0 else False , lst )
    print(list(it))

    25,什么是匿名函数?匿名函数有什么作用?

    lambda 匿名函数 : 用一句话表达只有返回值的无名函数
    lambda 参数 : 返回值

    26,Python递归的最大层数?

    官方:1000
    实测:994 ~ 1000
    
    import sys
    sys.setrecursionlimit(999999) # 修改递归的最大深度,mac能达到30000

    27,什么是迭代器?什么是可迭代对象?

    迭代器:具有__iter__()和__next__()方法
    可迭代对象:具有__iter__()方法
    
    
    dir(数据) 可以查看该数据的内部系统成员
    可迭代对象 => 迭代器  把不能直接被next获取 => 可直接获取到该数据的一个过程

    28,什么是生成器?

    生成器的本质就是迭代器,可以自定义迭代的逻辑
    创建方式两种:
        (1)生成器表达式 (推导式)  (i for i in range(3))
        (2)生成器函数   (含有yield关键字)

    29,什么是装饰器及应用场景?

    装饰器的本质就是闭包
    在不修改原有代码的前提下,额外增加新功能就是装饰器
    
    应用:登录认证,property类,框架(django,flask,@app.route("/",methdos=["GET","POST"]))

    30,什么是反射及应用场景?

    # 通过字符串去操作类对象 或者 模块中的属性方法
    
    hasattr getattr setattr delattr
    
    应用: 可以配合用户的操作或者输入,调用其中的成员,api接口中

    31,写一个普通的装饰器。

    def wrapper(func):
        def inner(*args,**kwargs):
            res = func(*args,**kwargs)
            print("and you")
            return res
            
        return inner
    
    @wrapper
    def func():
        print("i am fine 3q")
    
    func()

    32,写一个带参数的装饰器。

    def outer(n):
        def wrapper(func):
            def inner1(*args,**kwargs):
                res = func(*args,**kwargs)
                print("我是大王")
                return res
                
            def inner2(*args,**kwargs):
                res = func(*args,**kwargs)
                print("大王叫我来巡山")
                return res
            
            if n == "alex":
                return inner1
            else:
                return inner2
                
        return wrapper
    
    
    @outer("alex123") # outer("alex123") => wrapper =>@wrapper
    def func():
        print("i am fine 3q")
        
    func()

    33,求结果:

    def num():
        return [lambda x:i*x for i in range(4)]
    print([m(2) for m in num()])
    [6,6,6,6]
    """
    def出现的位置是函数的定义处
    函数() 出现的位置是函数的调用处
    (1)调用的时候,才会把函数中的代码,从上到下执行一遍,否则不执行
    (2)里面的func是一个闭包函数,延长了当前变量i的生命周期,最后一次i的值3,所以再去调用时候拿的3
    """
    详解

    34,def(a, b=[])这种写法有什么陷阱?

    b身上的默认值是列表,如果使用原来默认的参数,调用func函数
    会把几次调用的值都存放在同一个默认列表里
    """
    默认参数: 
        如果调用时,用户给实参了,那么使用用户的
        如果调用时,用户没给实参,那么使用默认的(早已存在内存中的这个列表)
        
    默认值会提前在内存中驻留,在使用时,才能调取,在定义函数的时候就提前开辟了空间
    """
    详解

    35,看代码写结果

    def func(a,b=[]):
        b.append(a)
        return b
    v1 = func(1)
    v2 = func(2,[10,20])
    v3 = func(3)
    print(v1,v2,v3)
    [1,3],[10,20,2],[1,3]

    36,看代码写结果

    def func(a,b=[]):
        b.append(a)
        return b
    v1 = func(1)
    print(v1)
    v2 = func(2,[10,20])
    print(v2)
    v3 = func(3)
    print(v3)
    [1]
    [10,20,2]
    [1,3]

    37,请编写一个函数实现将ip地址换成一个整数。

    如 10.3.9.12 转换规则为:
    10 00001010
    3 00000011
    9 00001001
    12 00001100
    再将以上二进制拼接起来计算十进制结果:00001010 00000011 00001001 00001100 = ?
    # ljust   原字符串居左,填充符号
    # rjust   原字符串居右,填充符号
    # 方法一
    ip = "10.3.9.12"
    strvar = ""
    for i in ip.split("."):
        bin_str = str(bin(int(i)))[2:]
        # 总长度是8 原字符串居右
        strvar += bin_str.rjust(8,"0")
    print(strvar)
        
    # 把二进制字符串转换成十进制,默认转换时,是十进制
    print(int(strvar,2))
    
    # 方法二
    ip = "10.3.9.12"
    strvar = ""
    for i in ip.split("."):
        # format 将整型转化成二进制,不够8位的拿0补位
        strvar += format(int(i) , "08b")
    print(int(strvar,2))

    38,请查找一个目录下的所有文件(可能存在文件嵌套)

    # 方法一 (递归写法)
    import os
    def getallsize(pathvar):
        size = 0
        lst = os.listdir(pathvar)
        print(lst)
        for i in lst:
            pathvar2 = os.path.join(pathvar,i)
            print(pathvar2)
            
            # 判断是否是文件
            if os.path.isfile(pathvar2):
                size += os.path.getsize(pathvar2)
            # 判断是否是文件夹
            elif os.path.isdir(pathvar2):
                size += getallsize(pathvar2)
    
            print(size)
        
        return size
        
    # "E:串讲基础day2	est1.txt"
    pathvar = r"E:串讲基础day2	est"
    res = getallsize(pathvar)
    # print(res)
    
    # 方法二
    import os
    
    # os.walk() => 生成器
    pathvar = r"D:ReptilePycPc"
    gen = os.walk(pathvar)
    
    for root, dirs, files in gen:
        for name in files:
            pathvar = os.path.join(root, name)
            print(pathvar)

    39,求结果:

    import math
    print (math.floor(5.5))
    5
    """
    floor    地板除
    
    ceil    天花板除
    
    round
            round n.5 奇进偶不进
            print(round(4.5))    4
            print(round(5.5))    6
            print(round(4.52))  5
    """
    拓展

    40,是否使用过functools中的函数?其作用是什么?

    wraps    # 在装饰器中使用,如果想要保留原来函数的属性,加上wraps
    
    reduce   # 累计算
    # 在装饰器中使用,如果想要保留原来函数的属性,加上wraps
    from functools import wraps
    
    
    def wrapper(func):
        @wraps(func)
        def inner(*args, **kwargs):
            res = func(*args, **kwargs)
            print("and you")
            return res
    
        return inner
    
    
    @wrapper
    def func():
        print("i am fine 3q")
    
    
    func()
    print(func)
    
    # def abc():
    # pass
    # print(abc)
    详解

    41,re的match和search区别?

    match:    从开头进行查找,查找到就停止,找不到返回None
    search: 查找全文,找到就停止,找不到就返回None

    42,用Python匹配HTML tag的时候,<.*><.*?>有什么区别?

    .* 贪婪匹配 匹配多个任意字符
    .*? 非贪婪 只匹配一次

    43,如何生成一个随机数?

    import random
    
    random.random()    # 生成随机小数,0<= x < 1

    44,super的作用?

    # 用来解决多继承之间复杂的调用关系使用super
    在多继承中, 如果出现了多个同名方法
    super在调用的时候, 会按照mro列表的继承顺序依次调用
    类.mro() = > lst
    详解

    45,双下划线和单下划线的区别?

    双线划线:__ 是Python中强制定义为私有
    单下划线:_  是程序员约定的私有方法

    46,@staticmethod和@classmethod的区别?

    一个静态方法, 一个类方法
    一个静态方法: (无论是对象还是类, 都可以调用, 不会默认传递任何参数)
    一个类方法: (无论是对象还是类, 都可以调用, 会默认传递类这个参数)

    47,实现一个单例模式(加锁)

    from threading import Lock
    
    
    class MyClass(object):
        __obj = None
        lock = Lock()
    
        def __new__(cls, *args, **kwargs):
            with cls.lock:
                if not cls.__obj:
                    cls.__obj = object.__new__(cls)
                return cls.__obj
    
    
    obj1 = MyClass()
    obj2 = MyClass()
    print(obj1, obj2)

    48,栈和队列的区别?

    栈:先进后出,或者后进先出
    队列:先进先出

    49,一下代码输出是什么?请给出答案并解释。

    class Parent(object):
        x = 1
    class Child1(Parent):
        pass
    class Child2(Parent):
        pass
    print Parent.x, Child1.x, Child2.x
    
    Child1.x = 2
    print Parent.x, Child1.x, Child2.x
    
    Parent.x = 3
    print Parent.x, Child1.x, Child2.x
    """
    1,1,1
    两个child都继承了parent,并没有自己的属性或方法
    
    
    1,2,1
    child1添加了属性,就近原则使用自己x的值,child2没有,继承父类
    
    
    3,2,3
    parent和chile1有自己的x方法,就近使用自己的,chiild2没有自己的x,继承父类中的x
    """

    50,参考下面代码片段:

    class Context:
        pass
    with Content() as ctx:
        ctx.do_something()
    请在Context类下添加代码完成该类的实现
    class Context():
        def __enter__(self):
            return self
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            # 相当于在最后,执行了文件的关闭操作,fp.close()
            print("abc123")
    
        def do_something(self):
            print(1111)
    
    
    with Context() as ctx:
        ctx.do_something()
        print(ctx)
    
    # 自动实现了关闭操作
    # with open("文件") as fp:
    #     res = fp.read()

    可选题

    1,如何获取列表中第二大的值?

    # 去重
    lst = set([98,1,100,3,-100,50,100,100])
    res = sorted(lst)
    res_new = res[-2]
    print(res_new)

    2,简述Python内存管理机制。

    计数器,垃圾回收,内存池
    # 一.计数器
    特点:引用技术如果是0,把这个值从内存中释放掉
    
    缺点:在维护引用计数时,又可能数据产生循环引用,造成数据不能删除,造成内存泄漏
    
    # 二.垃圾回收:引用计数为主,标记清除和分带回收为辅
    标记清除 : 检测标记该对象,避免出现循环引用不能删除的现象
    分带回收 :
        把内存中的数据分成三个区域: 新生代0,老年代1,永久代2
        新生代0数据超过700 , 或者老年代1,永久代2数据超过10,自动触发内存中的垃圾回收机制
        新生代0触发将清除所有三代的区域
        老年代1触发会清理1,2代
        永久代2触发只会清理自己
    
    # 三.内存池
    # 在同一个文件当中 (python3.6)
    # -->Number 部分
        1.对于整型而言,-5~正无穷范围内的相同值 id一致
        2.对于浮点数而言,非负数范围内的相同值 id一致
        3.布尔值而言,值相同情况下,id一致
        4.复数在 实数+虚数 这样的结构中永不相同(只有虚数的情况例外)
    # -->容器类型部分
        5.字符串 和 空元组 相同的情况下,地址相同
        6.列表,元组,字典,集合无论什么情况 id标识都不同 [空元组例外]
    # 在不同的文件当中
        小数据池 ; 比如整型默认开辟 -5~256 这么多数据提前在内存中驻留

    3,简述Python的垃圾回收机制。

    垃圾回收:引用计数为主,标记清除和分带回收为辅
    标记清除 : 检测标记该对象,避免出现循环引用不能删除的现象
    分带回收 :
        把内存中的数据分成三个区域: 新生代0,老年代1,永久代2
        新生代0数据超过700 , 或者老年代1,永久代2数据超过10,自动触发内存中的垃圾回收机制
        新生代0触发将清除所有三代的区域
        老年代1触发会清理1,2代
        永久代2触发只会清理自己

    4,请用两个队列来实现一个栈。

    """
    栈   : 先进后出,后进先出
    队列 : 先进先出,后进后出
    """
    from queue import Queue
    
    
    class Stack():
        def __init__(self):
            self.master_queue = Queue()
            self.minor_queue = Queue()
    
        def push(self, val):
            # 入栈
            self.master_queue.put(val)
    
        def pop(self):
            # 出栈
            # 如果队列中没有任何值,直接返回None
            if self.master_queue.qsize() == 0:
                return None
    
            while True:
                # 当队列总长度为1的时候,循环终止,把最后一个元素拿出来,为了满足栈后进先出的特点
                if self.master_queue.qsize() == 1:
                    value = self.master_queue.get()
                    break
    
                #  剩下还没有拿出来的元素,暂时放在2号队列中存储
                self.minor_queue.put(self.master_queue.get())
                """
                    minor_queue(1)
                    master_queue(2 3 4)
                    
                    minor_queue(2)
                    master_queue(3 4)
    
                    minor_queue(3)
                    master_queue(4)
                """
            # 交换队列,重新循环,继续去最后一个值,如法炮制
            self.master_queue, self.minor_queue = self.minor_queue, self.master_queue
            return value
    
    
    obj = Stack()
    obj.push("a")
    obj.push("b")
    obj.push("c")
    
    print(obj.pop())  # c
    print(obj.pop())  # b
    print(obj.pop())  # a
    print(obj.pop())  # a

    5,请用Python实现一个链表。

    class Node():
        def __init__(self, value, next):
            self.value = value
            self.next = next
    
    
    head = Node("", None)
    last = head
    
    for i in range(5):  # v0 v1 v2 v3 v4
        node = Node("v%s" % i, None)
        last.next = node
        last = node
    
    # 查看链表的关系
    print(head.value)
    print(head.next.value)
    print(head.next.next.value)
    print(head.next.next.next.value)
    print(head.next.next.next.next.value)
    print(head.next.next.next.next.next.value)
    
    # print(head.next)
    print("<========>")

    6,请用Python实现链表的逆转。

    def reverse_link_list(head):
        # 要是空的,或者None,直接返回head
        if not head or not head.next:
            return head
    
        # 获取上一个节点对象
        prev_node = None
        # 获取下一个节点对象
        next_node = head.next
        # 获取当前节点对象
        current_node = head
    
        while True:
            # 修改next,所指向的对象
            current_node.next = prev_node
            # 如果下一个阶段对象是None
            if not next_node:  # not None
                break
    
            # 重新获取上一个对象,即把当前丢向单独存一份,以准备第二次循环时插进next属性中
            prev_node = current_node
            # 重新获取当前对象 , 即把下一个对象单独存储起来(下个)
            current_node = next_node
            # 重新获取下一个对象,即把下一个对象单独存储起来,所指向的下个新对象赋值给next_node(下下个)
            next_node = current_node.next
        return current_node
    
    
    head = reverse_link_list(head)
    
    print(head.value)
    print(head.next.value)
    print(head.next.next.value)
    print(head.next.next.next.value)
    print(head.next.next.next.next.value)
    print(head.next.next.next.next.next.value)
  • 相关阅读:
    4星|《态度》:吴军博士写给读高中和大学的女儿们的信
    2星|宇见《洞察力:让营销从此直指人心》:营销讲师自创的理论,逻辑较差,洞察力不用提
    1星|《社群X平台》:没有实际工作经验的职业写手拼凑而成
    3星|《一课经济学》:70年前的经济学思想普及读物,现在看还不过时
    3.5星|《戴维斯王朝》:业绩媲美巴菲特的投资人家族的故事
    3.5星|《行为设计学:零成本改变》:明确的、可操作的、短期的、可以引起情感共鸣的目标,更有助于个人或组织做出改变
    1星|《讲法:从说教到赋能》:用伪科学概念说理,对建构主义的解释与理解比较牵强
    2星|《谁站在马云背后》:总裁律师的职责、素养、趋势。信息浓度较低,案例偏老旧肤浅
    2星|简七《巴比伦富翁新解》:浅显的理财原则,目测作者长于理财培训而不是理财实战
    使用 Visual Studio 部署 .NET Core 应用 ——.Net Core 部署到Ubuntu 16.04
  • 原文地址:https://www.cnblogs.com/linglichong/p/12369837.html
Copyright © 2020-2023  润新知