恶魔的微笑111

导航

python基础面试题--1

python面试基础篇-----1

  1. 简述列举了解的编程语言及语言间的区别
java:编译型语言 
c语言:编译型语言
python:解释型语言
编译型语言和解释型语言的区别
编译型语言
	优点:
		运行速度快,执行效率高
	缺点:
		编译时间长,需要根据操作系统环境编译不同的可执行文件
解释型语言
	优点:开发效率高,有良好的兼容性,灵活
	缺点:运行速度慢,性能上不如编译型语言
  1. Python2和python3的区别

    • Python2:源码不统一,源码有重复,python3,源码统一,源码不重复

    • Python2除法的时候返回的是整数(向下取整),python3返回的是浮点数

    • python3中的input获取的是字符串,python2中获取的是数据本身

    • Python3使用的是Unicode,Python2中使用 ASCII 码

    • python3 iter()和_iter_()都有 python2 只有 iter()

    • Python2中没有提供线程池,python3之后解释器才提供了线程池.

    • Python2: python2.2 之前都是经典类,python2.2之后出现了新式类,继承object就是新式类

      Python3: 只有新式类,不管你继不继承object都是新式类

  2. 看代码,写结果

    v1 = 1 or 2
    结果:1
    
    v2 = 3 and 7 or 9 and 0
    结果:7
    
    规则:
    	and的运算,都为真才为真,有一个是假就是假
    	and的运算,都为真的时候选择and后边的内容
    	and的运算,都为假时选择and前边的内容
    	
    	or的运算,只要有一个真就是真
    	or的运算,都为真时选择or前边的内容
    	or的运算,都为假时选择or后边的内容
    	
    	非 ---不是
    	  not  True = False
    	  
    优先级:
    	()>not>and>or
    
  3. 比较以下值有什么不同

    v1 = [1,2,3]     列表
    v2 = [(1),(2),(3)]  列表套元组
    v3 = [(1,),(2,),(3,)] 列表嵌套元组
    
  4. 一行代码实现数值互换

    a = 1
    b = 2
    a,b = b,a
    
  5. python中单引号,双引号,三引号的区别

    单引号、双引号和三引号没区别,只是在同一个字符串中,一种引号只能用一次

    三引号还能用作多行注释

  6. is和==的区别

    is 比较两个对象的id是否相等,==是比较两边的对象是否相等

  7. python中如何实现tuple和list的转化

    a = (1,2,3,4,5)
    b = list(a)
    
  8. 如何实现字符串name='老男孩'反转

    name = "老男孩"
    l = reversed(name)
    print(''.join(l))
    字符串切片
    l= name[::-1]
    
  9. 两个set如何获取交集、并集、差集

    s1 = {"刘能", "赵四", "⽪⻓⼭"}
    s2 = {"刘科⻓", "冯乡⻓", "⽪⻓⼭"}
    交集  s1&s2 两个集合中的共有元素
    并集  s1|s2 两个集合中的全部元素
    差集  s1-s2 第一个集合中单独的元素
    
  10. 那些情况下, y != x - (x-y)会成立?

    x,y都为非空集合 且不为子父关系

  11. Python中如何拷贝一个对象

    使用深拷贝的方式进行拷贝

  12. 简述 赋值、浅拷贝、深拷贝的区别

    赋值(=),就是创建了对象的一个新的引用,修改其中任意一个变量都会影响到另一个。
    浅拷贝:创建一个新的对象,但它包含的是对原始对象中包含项的引用(如果用引用的方式修改其中一个对象,另外一个也会修改改变)
    深拷贝:创建一个新的对象,并且递归的复制它所包含的对象
    
  13. pass的作用

    pass是占位符,保持程序结构的完整性

  14. 看代码,写结果

    import copy
    a = [1,2,4,5,['b','c']]
    b = a
    c = copy.copy(a)浅
    d = copy.deepcopy(a) 深
    
    a.append(5) 
    [1,2,4,5,['b','c'],5]
    a[4].append('d')
    [1,2,4,5,['b','c','d'],5]
    
    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]
    
  15. 用Python实现9 * 9 乘法表

    for i in range(1,10):
        for j in range(1,i+1):
            print("%s*%s=%s"%(i,j,i*j),end=' ')  
        print(' ')
    
  16. 用Python显示一个斐波那契数列

    def fib(n):
      if n==1 or n==2:
        return n
      return fib(n-1) + fib(n-2)
    n = int(input())
    print('斐波那契数列第%s个是'%(n),fib(n))
    
    方法二:
    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
    
  17. 如何删除列表中重复的值

    lst=list(set(list))

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

    with open(etl_log.txt, 'r') as f:
    	for i in f:
            print(i,end=' ')
    
  19. a = dict(zip(("a","b","c","d","e"),(1,2,3,4,5))) 请问a是什么

    {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
    
  20. lambda关键字的作用?

    lambda是匿名函数,能提高代码的执行效率,增加可读性
    lambda 参数 : 返回值
    
  21. *arg**kwarg作用?

    *arg在定义函数时接受多余的位置参数,**kwarg接受多余的关键字参数
    *arg 把多余的位置参数转化为元组
    **kwarg 把多余的关键字参数转换为字典
    
  22. 如何在函数中设置一个全局变量

    使用global
    global  变量名
    
  23. filter、map、reduce的作用

    map  作用:便于对数组中的每个元素进行操作   是用同样方法把所有数据都改成别的
    map(func,iterable) => 返回迭代器
    
    lst = [1,2,3]
    it = map(lambda x : x*3 , lst)
    print(list(it))
    
    reduce 作用:对数组中的元素进行汇总  是用某种方法依次把所有数据丢进去最后得到一个结果
    from functools import reduce
    # reduce(func,iterable) => 最后计算的值
    # [5,4,8,8] => 5488
    lst = [5,4,8,8]
    res = reduce(lambda x,y : x*10 + y ,lst )
    print(res , type(res))
    
    filter 作用:过滤 是筛选出其中满足某个条件的那些数据
    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))
    
  24. 什么是匿名函数?匿名函数有什么作用

    匿名函数:为了解决那些功能很简单的需求而设计的一句话函数
    函数名 = lambda 参数 :返回值
    
    作用:能够简化代码,能作为参数传递,提高执行效率,节省空间
    
  25. Python递归的最大层数

    官方给出的结果是1000,实测在998左右
    
  26. 什么是迭代器?什么是可迭代对象?

    含有__iter__和__next__方法 (包含__next__方法的可迭代对象就是迭代器)
    具有__iter__方法的就是可迭代对象。
    
  27. 什么是生成器

    包括含有yield这个关键字,生成器也是迭代器,调动next把函数变成迭代器
    
  28. 什么是装饰器及应用场景

    能够在不修改原函数代码的基础上,在执行前后进行定制操作,闭包函数的一种应用
    应用场景:
    	django的权限验证
    	计算函数的运行次数和运行时间
    	插入日志
    
  29. 什么是反射及应用场景

    反射就是通过字符串的形式,导入模块;通过字符串的形式,去模块寻找指定函数,并执行。利用字符串的形式去对象(模块)中操作(查找/获取/删除/添加)成员
    
    应用场景
    	django中的类视图
    
  30. 写一个普通的装饰器。

    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()
    
  31. 写一个带参数的装饰器。

    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()
    
  32. 求结果

    def num():
      return [lambda x:i*x for i in range(4)]
    print([m(2) for m in num()])
    
    结果[6,6,6,6]
    
  33. def(a, b=[])这种写法有什么陷阱

    b身上的默认值是列表,如果使用原来默认的参数,调用func函数
    会把几次调用的值都存放在同一个默认列表里
    
  34. 看代码写结果

    def func(a,b=[]):
        b.append(a)
    	return b
    
    v1 = func(1)  [1,3]
    v2 = func(2,[10,20])[10,20,2]
    v3 = func(3)[1,3]
    print(v1,v2,v3)  先加载,后打印
    
  35. 看代码写结果

    def func(a,b=[]):
        b.append(a)
    	return b
    
    v1 = func(1)
    print(v1)[1]
    v2 = func(2,[10,20])
    print(v2)[10.20,2]
    v3 = func(3)
    print(v3)[1,3]
    
  36. 请编写一个函数实现将IP地址转换成一个整数

    如 10.3.9.12 转换规则为:
            10            00001010
             3            00000011
             9            00001001
            12            00001100
            
    再将以上二进制拼接起来计算十进制结果:00001010 00000011 00001001 00001100 = ?
    
    # 方法一
    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))
    
    
  37. 请查找一个目录下的所有文件(可能存在文件嵌套)。

    os.walk()  生成目录树下的所有文件名
    
  38. 求结果

    import math   floor向下取整   ceil向上取整    round 奇进偶不进(n.5时)
    print (math.floor(5.5))
    5
    
  39. 是否使用过functools中的函数?其作用是什么?

    functools用于高阶函数:指那些作用于函数或者返回其他函数的函数。通常情况下,只要是可以被当做函数调用的对象就是这个模块的目标。
    
    用于修复装饰器
    import functools
     
    def deco(func):
        @functools.wraps(func)  # 加在最内层函数正上方
        def wrapper(*args, **kwargs):
            return func(*args, **kwargs)
        return wrapper
        
    @deco
    def index():
        '''哈哈哈哈'''
        x = 10
        print('from index')
    print(index.__name__)
    print(index.__doc__)
     
    # 加@functools.wraps
    # index
    # 哈哈哈哈
    # 不加@functools.wraps
    # wrapper
    # None
    
  40. re的match和search区别?

    re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none。
    re.search 扫描整个字符串并返回第一个成功的匹配。
    
  41. 用Python匹配HTML tag的时候,<.>和<.?>有什么区别?

    贪婪匹配( <.> )和非贪婪匹配(<.?> )
    ? 匹配0个或一个
    
  42. 如何生成一个随机数?

    import random
    print(random.random())          # 用于生成一个0到1的随机符点数: 0 <= n < 1.0
    print(random.randint(1, 1000))  # 用于生成一个指定范围内的整数
    
  43. super的作用?

    用于子类继承基类的方法
    按照c3算法的顺序执行
    用来解决多继承之间复杂的调用关系
    
  44. 双下划线和单下划线的区别?

    双下划线是程序规定的私有方法
    单下划线是程序员约定的方法
    
  45. @staticmethod和@classmethod的区别?

    @staticmethod不需要表示自身对象的self和自身类的cls参数,就跟使用函数一样
    @classmethod也不需要self参数,但第一个参数需要是表示自身类的cls参数。
    
    如果在@staticmethod中要调用到这个类的一些属性方法,只能直接类名.属性名或类名.方法名。 
    而@classmethod因为持有cls参数,可以来调用类的属性,类的方法,实例化对象等,避免硬编码。 
    
  46. 实现一个单例模式(加锁)。

    import threading
    import time
    class Singleton:
        __instance = None
        lock = threading.RLock()
    
        def __init__(self, name):
            self.name = name
        def __new__(cls, *args, **kwargs):
            if cls.__instance:
                return cls.__instance
            with cls.lock:
                if cls.__instance:
                    return cls.instance
                time.sleep(0.1)
                cls.__instance = object.__new__(cls)
            return cls.__instance
    
    
    def task():
        obj = Singleton('x')
        print(obj)
    
    for i in range(10):
        t = threading.Thread(target=task)
        t.start()
    # 执行1000行代码
    data = Singleton('a4sdfasdf')
    print(data)
    
    
  47. 栈和队列的区别?

    栈是先进后出
    队列是先进先出
    
  48. 以下代码输出是什么? 请给出答案并解释。

    class Parent(object):
        x = 1
    
    class Child1(Parent):
        pass
    
    class Child2(Parent):
        pass
    
    print Parent.x, Child1.x, Child2.x
    1  1    1
    Child1.x = 2
    print Parent.x, Child1.x, Child2.x
    1   2  1 
    Parent.x = 3
    print Parent.x, Child1.x, Child2.x
    
    3 2 3
    
  49. 参考下面代码片段

    class Context:
        def __enter__(self):
            return self
        def __exit__(self,exc_type, exc_val, exc_tb):
            #在最后执行,执行文件关闭的操作
            print("asa")
         def do_something(self):
            print('123')
    
    with Content() as ctx:
        ctx.do_something()
    请在Context类下添加代码完成该类的实现
    

第二部分 可选题

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

    sorted()[-2]   所有容器类型都可以通过sorted进行排序
    
  2. 简述Python内存管理机制。

     Python 是动态类型语言,对象的类型和内存占用都是运行时确定的,一边运行一边解释。
     python解释器通过以下三种方式来管理内存
     	1.对象的引用次数
     		引用计数特点:如果引用计数如果是0,就把这个值从内存中释放掉
     		缺点:在维护引用计数时,有可能数据产生循环引用,造成数据不能删除,造成内存泄漏
     	2.垃圾回收机制
     		引用计数为主,标记清除和分带回收为辅
     		标记清除:检测标记该对象,避免出现循环引用不能删除的现象
     			标记清除就是一样的变量名引用多少次,只需要一次删除就都删掉了
     		分带回收:把内存中的数据分成三个区域:新生代0,老年代1,永久带2  
            
     	3.内存池机制
    
  3. 简述Python的垃圾回收机制。

    Python的GC模块主要运用了“引用计数”(reference counting)来跟踪和回收垃圾。在引用计数的基础上,还可以通过“标记-清除”(mark and sweep)解决容器对象可能产生的循环引用的问题。通过“分代回收”(generation collection)以空间换取时间来进一步提高垃圾回收的效率。没有变量引用及回收
    
  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
    
    

    方法二:

    class Stock:
        def __init__(self):
            self.queueA = []
            self.queueB = []
    
        def push(self, node):
            self.queueA.append(node)
    
        def pop(self):
            if len(self.queueA) == 0:
                return None
            while len(self.queueA) != 1:
                self.queueB.append(self.queueA.pop(0))
            self.queueA, self.queueB = self.queueB, self.queueA  # 交换是为了下一次的pop
            return self.queueB.pop()
    
    
    if __name__ == '__main__':
        times = 5
        testList = list(range(times))
        testStock = Stock()
        for i in range(times):
            testStock.push(testList[i])
        print(testList)
        for i in range(times):
            print(testStock.pop(), ',', end='')
            
    [0,1,2,3,4]
    4 3 2 1 0
    

    两个栈实现一个队列

    class Queue:
        def __init__(self):
            self.stockA=[]
            self.stockB=[]
        def push(self, node):
            self.stockA.append(node)
        def pop(self):
            if self.stockB==[]:
                if self.stockA==[]:
                    return None
                else:
                    for i in range(len(self.stockA)):
                        self.stockB.append(self.stockA.pop())
            return self.stockB.pop()
    
    if __name__=='__main__':
        times=5
        testList=list(range(times))
        testQueue=Queue()
        for i in range(times):
            testQueue.push(testList[i])
        print(testList)
        for i in range(times):
            print(testQueue.pop(),',',end='')
    
  5. 请用Python实现一个链表。

    next存的是下一个节点的node对象,这个对象有value就是该节点的内容,next就是再下一个节点的对象
    # ### (1) 创建链表
    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)
    
  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)
    

posted on 2020-02-26 11:54  恶魔的微笑111  阅读(161)  评论(0编辑  收藏  举报