Java有八股文,但是Python面试好像这方面的资料比较少,所以打算自己整理一些写出来,给要找工作的小伙伴个参考crt语句生成器,如果大家有一些好的面试题也可以私聊我

下面是某软国际的面试题,感觉整体考察的是基础部分

1.请说一下你对迭代器和生成器的区别?

大家回家这个题的时候,也可以提一下可迭代对象(iterable),可迭代对象是一种可以逐一返回其成员元素的对象crt语句生成器,它可以在每次的迭代过程中产生一个成员元素

迭代器是一种可以被遍历的对象,并且能作用于next()函数。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。 迭代器只能往后遍历不能回溯,不像列表,你随时可以取后面的数据,也可以返回头取前面的数据。

迭代器通常要实现两个基本的方法:iter() 和 next()

下面举个例子

lis=[1,2,3,4]
it = iter(lis)     	# 使用Python内置的iter()方法创建迭代器对象
next(it)           	# 使用next()方法获取迭代器的下一个元素
1
next(it)
2
next(it)
3
next(it)
4
next(it)            # 当后面没有元素可以next的时候,弹出错误
复制代码

我们也可以用迭代器实现一个for循环

d_iter = iter(range(5))
while True:
    try:
        print(next(d_iter))
    except StopIteration:
        break
复制代码

上面我们自己写的代码等价于

for i in range(5):
    print(i)
复制代码

接下来我们聊下生成器

有时候,序列或集合内的元素的个数非常巨大,如果全制造出来并放入内存,对计算机的压力是非常大的。

如果元素可以按照某种算法推算出来,需要就计算到哪个,就可以在循环的过程中不断推算出后续的元素,而不必创建完整的元素集合,从而节省大量的空间。

在Python中,这种一边循环一边计算出元素的机制,称为生成器:generator。

生成器在 Python 的写法是用小括号括起来,g = (x * x for x in range(1, 4)),即初始化了一个生成器。

可以通过next()函数获得generator的下一个返回值,这点和迭代器非常相似

next(g)
1
next(g)
4
next(g)
9
next(g)
复制代码

除了使用生成器推导式,我们还可以使用yield关键字。

def createNums():
    print("----func start------")
    a,b = 0,1
    for i in range(5):
        # print(b)
        print("--1--")
        yield b
        print("--2--")
        a,b = b,a+b    # a,b = 1, 1     a,b = 1,2
        print("--3--")
    print("----func end------")
g= createNums()
复制代码

在 Python中,使用yield返回的函数会变成一个生成器(generator)。 在调用生成器的过程中,每次遇到yield时函数会暂停并保存当前所有的运行信息,返回yield的值。并在下一次执行next()方法时从当前位置继续运行。

2.什么是线程安全?

线程安全,就要提到Python中的线程共享全局变量导致资源竞争,如果两个线程同时对一个变量进行写操作,我们看下会发生什么

import threading
import time
num = 0
def task1(nums):
    global num
    for i in range(nums):
        num += 1
    print("task1----num=%d" % num)
def task2(nums):
    global num
    for i in range(nums):
        num += 1
    print("task2----num=%d" % num)
def main():
    t1 = threading.Thread(target=task1, args=(1000000,))  
    t2 = threading.Thread(target=task2, args=(1000000,))
    t1.start()
    t2.start()
    time.sleep(5)
    print("main-----num=%d" % num)
if __name__ == "__main__":
    main()
复制代码

打印结果

task1----num=1000000
task2----num=1193380
main-----num=1193380
复制代码

因为这是多线程的, 所以cpu在处理两个线程的时候, 是采用雨露均沾的方式, 可能在线程一刚刚将num值+1还没来得及将新值赋给num时, 就开始处理线程二了, 因此当线程二执行完全部的num+=1的操作后, 可能又会开始对线程一的未完成的操作, 而此时的操作停留在了完成运算未赋值的那一步, 因此在完成对num的赋值后, 就会覆盖掉之前线程二对num的+1操作

那我们如何解决呢?

可以通过加锁,或者采用队列的方式来解决资源竞争的问题,这里我就不展开说了

3.Python中数组有哪些类型?

List Tuple Dictionary 
复制代码

4.python 中 yield 的用法?

yield 简单说来就是一个生成器,这样函数它记住上次返 回时在函数体中的位置。对生成器第 二次(或n 次)调用跳转至该函 次)调用跳转至该函数。

5. Python中pass语句的作用是什么?

pass语句什么也不做,一般作为占位符或者创建占位程序,pass语句不会执行任何操作。

6.谈谈你对GIL锁对python多线程的影响?

GIL全局解释器锁,这是一段官网对GIL的说明

In CPython, the global interpreter lock, or GIL, is a mutex that prevents multiple 
native threads from executing Python bytecodes at once. This lock is necessary mainly 
because CPython’s memory management is not thread-safe. (However, since the GIL 
exists, other features have grown to depend on the guarantees that it enforces.)
复制代码

Python解释器有很多,CPython、JPython、iPython,在CPython解释器中GIL是一把互斥锁,用来阻止同一个进程下的多个线程同时执行

每个CPU在同一时间只能执行一个线程(在单核CPU下的多线程其实都只是并发,不是并行,并发和并行从宏观上来讲都是同时处理多路请求的概念。但并发和并行又有区别,并行是指两个或者多个事件在同一时刻发生;而并发是指两个或多个事件在同一时间间隔内发生。)

重点:

7. Python里面如何拷贝一个对象?

浅拷贝:创建一个新的对象,但它包含的是对原始对象中包含项的引用(如果用引用的方式修改其中一个对象,另外一个也会修改改变)

深拷贝:创建一个新的对象,并且递归的复制它所包含的对象(修改其中一个,另外一个不会改变)

下面给大家举个例子

from copy import deepcopy
a = [11,22]
b = a
print(id(a))
print(id(b))
import copy
c = deepcopy(a)
a.append(33)
# [11, 22, 33]
print(a)
# [11, 22]  c是深拷贝 相当于创建了新的对象 不受影响
print(c)
复制代码

8. 递归函数停止的条件

递归的终止条件一般定义在递归函数内部,在递归调用前要做一个条件判断,根据判断的结果选择是继续调用自身,还是return;返回终止递归。

终止的条件:

举个例子

def factorial(n):
    if n == 0:
        return 1
    else:
        return n * factorial(n-1)
复制代码

9. 什么是闭包?

在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用。这样就构成了一个闭包。

给大家举个例子

def outer_function(x):
    def inner_function(y):
        return x + y
    return inner_function
closure = outer_function(10)
result = closure(5)
print(result)  # Output: 15
复制代码

10. linux下管道符的作用?

一个命令的输出结果可以通过管道做为另一个命令的输入,就是管道符的作用.

这个命令就是查看Linux系统中是否运行了Redis服务

ps -aux | grep redis
复制代码