校招python常见面试知识点归纳

1、*arg、**kargs的用法?

*args是可变参数,args接受的是一个元组,**kargs是关键字参数,接受的是一个字典。

2、python的基本数据类型?

Number(数字)、String(字符串)、List(列表)、Tuple(元组)、set(集合)、Dict(字典)
不可变对象有:数值类型,int ,float,字符串,元组
可变对象:列表,字典,集合
可变对象:对象所指的值可以改变,改变时,值指向的内存单元不变,还是指向原来的地址,没有新开辟一块内存。
不可变对象:对象所指向的内存中的值不能被改变,当改变这个变量的时候,原来指向的内存中的值不变,变量不再指向原来的值,而是开辟一块新的内存,变量指向新的内存。

3、内置的数据结构有哪些?

tuple,list,dict,set
set和dict的区别在于有没有存储key对应的value,两者都不可以放入可变对象。

4、装饰器?

由于函数也是一个对象,而且函数对象可以被赋值给变量,所以变量也可以调用该函数。
在代码运行期间动态增加功能的方式,称之为装饰器。

5、list.sort()方法和内置函数sorted的区别

list.sort()方法会就地排序列表,也就是说不会将原列表复制一份。
sorted会新建一个列表作为返回值。
两者都有两个可选的关键字参数 reverse和key。

list的数据结构
列表是通过数组和链表实现的容器序列,容器序列存放的是他们所包含的仍以类型的对象的引用。

6、什么是可迭代对象?迭代器?

实现了方法__iter__的对象是可迭代的,实现了方法__next__的对象是迭代器。
通过对可迭代对象调用内置函数iter也可以实现一个迭代器。
可用dir函数查看对象的所有内置方法。

7、列表生成式?

列表生成式是一个可以生成列表的特定语法形式的表达式。可以帮助我们把一个序列或者其他可迭代类型的中的元素过滤或者加工,然后在新建一个列表。

8、生成器

构建生成器的两种方法:
a)使用类似列表生成式的方法,将列表换成元组。、
b)使用包含yield的函数完成。
生成器是一种使用普通函数语法定义的迭代器。
生成器有两个单独的部分组成:生成器的函数和生成器的迭代器。生成器的函数有def语句定义的,其中包含yield。生成器的迭代器是这个函数返回的结果。

9、装饰器

装饰器的作用就是为已经存在的对象添加新的功能。
装饰器是可调用对象,其参数是另一个函数(被装饰的函数)。装饰器可能会处理被装饰的函数,然后把它返回,或者将其替换成另一个函数或可调用对象。

装饰器的一大特点是:能把被装饰的函数替换成其他函数,装饰器在加载模块时立即执行。

10、setdefault 处理找不到的键

类似get,它也获取与指定键相关联的值,除此之外,当字典中不存在键时,为字典中添加指定的键值对。

11、dict和defaultdict的区别

在查找dict中没有的键时,dict会抛出一个keyerror
defaultdict则会让__getitem__返回一个默认值。

12、进程、线程和协程的区别

一、概念
1、进程:进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。每个进程都有自己的独立内存空间,不同进程间通过进程间通信来通信。
2、线程:线程是进程的一个实体,是CPU调度和分配一个基本单位,它是比进程更小的能独立运行的基本单位。线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源,但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源。线程间通信主要靠内存,上下文切换很快,资源开销较少,但比进程不够稳定容易丢失数据。
3、协程:协程是一种用户态的轻量级线程,协程的调度完全由用户控制。

二、区别与联系
1、进程与线程比较
线程是进程内的一个执行单位,也是进程内可调度实体。区别:
1)地址空间:线程是进程内的一个执行单元,进程内至少有一个线程,他们共享进程的地址空间,而进程有自己独立的地址空间。
2)资源拥有:进程是资源分配和拥有的单位,同一进程内的线程共享进程的资源。
3)线程是处理器调度的基本单位,但进程是系统调度。
4)二者都是处理多任务的方法,均可并发执行。
5)每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口吗,但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。

2、协程和线程的比较
1)一个线程可以有多个协程,一个进程也可以单独拥有多个协程。
2)线程进程都是同步机制,而协程是异步
3)协程能保留上一次调用时的状态,每次过程重入时,就相当于上一次调用的状态。

13、构造函数

构造函数也叫初始化函数,在类创建后自动调用它们,无需先访问函数再调用函数下的内容
例如 class FooBar:
def init(self):
self.somevar = 42
f = FooBar
f.somevar

14.del、remove、pop的区别

del根据位置删除元素,不返回任何值
pop根据位置弹出元素,没有参数就从数组末尾弹出元素,返回的是数组
remove根据值删除元素,默认删除从左到右第一个元素

15、数组和链表的区别

数组;数组存储值必须提前声明空间,因为数组存储是连续的,也因此数组查询的时间复杂度是O(1)
插入和删除的复杂度是O(n);
链表:不用连续存储,链表中每个位置都记录着下一个元素的位置信息。链表查询时间复杂度是O(n)
插入和删除复杂度是O(1)

16、python如何进行内存管理

在python中,使用了引用计数这一技术实现内存管理。当引用计数为0的时候,自动垃圾回收机制
就会回收这个对象。引用计数有循环引用的问题。
分代回收机制,主要用于解决循环引用的问题

17、python的内存池机制

在Python中,许多时候申请的内存都是小块的内存,这些小块内存在申请后,很快又会被释放,由于这些内存的申请并不是为了创建对象,所以并没有对象一级的内存池机制。这就意味着Python在运行期间会大量地执行malloc和free的操作,频繁地在用户态和核心态之间进行切换,这将严重影响Python的执行效率。为了加速Python的执行效率,Python引入了一个内存池机制,用于管理对小块内存的申请和释放。
Python提供了对内存的垃圾收集机制,但是它将不用的内存放到内存池而不是返回给操作系统。

18、python中的重载

函数重载的主要是为了解决两个问题:

  • 可变的参数类型
  • 可变的参数个数
    一个基本的设计原则是:仅仅当两个函数除了参数烈性和参数个数不同以外,其功能应该是完全相同的,此时才使用函数重载,如果两个函数的功能其实不同,那么不应该使用重载,而应当使用一个名字不同的函数。
    因为python可以接受任意类型的参数,如果函数的功能相同,那么python不用处理本身就可以实现可变的参数类型。
    对于可变的参数的个数,python的处理方法是缺省参数

在调用函数时,通常会传递参数,函数内部的代码保持不变,针对 不同的参数处理不同的数据。有位置传参、关键字传参、默认值参数、多值参数等。缺省参数就是含有默认值的参数。

19、新式类和旧式类

python3中所有的类都是新式类,新式类继承是根据C3算法从左到右广度优先,旧式类继承从左到右深度优先(MRO:方法解析顺序);
一个旧式类的深度优先的例子

class A():
    def foo1(self):
        print "A"
class B(A):
    def foo2(self):
        pass
class C(A):
    def foo1(self):
        print "C"
class D(B, C):
    pass

d = D()
d.foo1()

# A

按照经典类的查找顺序从左到右深度优先的规则,在访问d.foo1()的时候,D这个类是没有的…那么往上查找,先找到B,里面没有,深度优先,访问A,找到了foo1(),所以这时候调用的是A的foo1(),从而导致C重写的foo1()被绕过.

20、__new__和__init__的区别

  1. __new__是一个静态方法,而__init__是一个实例方法;
  2. __new__方法会返回一个创建的实例,而__init__什么都不返回;
  3. 只有在__new__返回一个cls的实例时,后面的__init__才不能被调用;
  4. 当创建一个新实例时调用__new__,初始化一个实例时用__init__

21、单例模式

单例模式一种常见的设计模式。它的核心结构中只包含一个被称为单例类的特殊类。通过单例模式可以保证系统中的一个类只有一个实例且易被外界访问,从而方便对实例个数进行控制并节约系统资源。如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。

1、使用__new__方法:

class Single(object):
    _instance = None
    def __new__(cls, *args, **kw):
        if cls._instance is None:
            cls._instance = object.__new__(cls, *args, **kw)
        return cls._instance


if __name__ == "__main__":
    a = Single()
    b = Single()
    print(id(a)==id(b))

2、共享属性
创建实力的时候把所有的__dict__指向同一个字典,这样它们具有相同的属性和方法。

class Borg(object):
    _state = {}
    def __new__(cls, *args, **kw):
        ob = super(Borg, cls).__new__(cls, *args, **kw)
        ob.__dict__ = cls._state
        return ob

class MyClass2(Borg):
    a = 1

3、装饰器版本

def singleton(cls):
    instances = {}
    def getinstance(*args, **kw):
        if cls not in instances:
            instances[cls] = cls(*args, **kw)
        return instances[cls]
    return getinstance

@singleton
class MyClass:
  ...

4、import方法
作为python的模块是天然的单例模式

class My_Singleton(object):
    def foo(self):
        pass

my_singleton = My_Singleton()

# to use
from mysingleton import my_singleton

my_singleton.foo()

22、Python的作用域

python中,一个变量的作用域总是由代码中被赋值的地方所决定。

当python遇到一个变量的话他会按照这样的顺序进行搜索:

本地作用域(Local)→当前作用域被嵌入的本地作用域(Enclosing locals)→全局/模块作用域(Global)→内置作用域(Built-in)

23、闭包

闭包是指延伸了作用域的函数,其中包含函数定义体中引用、但是不在定义体中定义的非全局变量。也就是说闭包可以访问定义体之外的定义的非全局变量。

例子:计算移动平均值,每次输入一个数,返回当前数和之前输入的所有数的平均值。
我们首先看一下不使用闭包,我们通常是如何实现这个功能的。

class Averager:
    def __init__(self):
        self.series = [] #给实例对象绑定一个属性series来存储每次输入的数

    def __call__(self, new_values):
        self.series.append(new_values)
        total = sum(self.series)
        print(total/len(self.series))

if __name__ == "__main__":
    avg = Averager()
    avg(10)
    #10.0
    avg(11)
    #10.5

使用闭包

def Averager():
    series = []
    def averager(new_values):
        series.append(new_values)
        total = sum(series)
        print(total/len(series))
    return averager # ************
if __name__ == "__main__":
    avg = Averager()
    avg(10)
    #10.0
    avg(11)
    #10.5

注意看使用闭包的时候,我们利用了一个嵌套函数,外层函数返回内部函数。不用闭包的时候,我们利用self.series存储历史值。使用闭包的时候,虽然series定义在本地作用域,看似每次调用Averager的时候,series都会重新被赋值为[],其实不然。闭包的作用就在于此,使用闭包的时候,series是一个自由变量(未在本地作用域绑定的变量),闭包函数能够引用自由变量,并使自由变量始终保存在内存中。

总结起来就是闭包只有在使用嵌套函数时使用,闭包是一个保留定义函数时存在的自由变量的绑定,虽然作用域不可用了,但是仍能使用这些绑定。

这里需要注意的是,这里自由变量series不能在内部函数中重新复制,我们这里因为series是列表是可变的数据类型,因此对它进行改变不会有问题。但如果我们改一下:

def Averager():
    count = 0
    total  =0
    def averager(new_values):
        count += 1
        total += new_values
        print(total/count)
    return averager

我们记录之前的历史值之和 和元素个数,按照上面的写法,会发现在编译器中会出现错误;原因在于count,total是不可变对象,在内部函数对其重新赋值,count和total就会变成局部变量而不是自由变量。那么对于不可变对象该如何做呢?
nonlocal,利用关键字nonlocal 将count和total声明为非局部变量。

def Averager():
    count = 0
    total = 0
    def averager(new_values):
        nonlocal count, total
        count += 1
        total += new_values
        print(total/count)
    return averager

24、GIL线性全局锁

线程全局锁(Global Interpreter Lock),即Python为了保证线程安全而采取的独立线程运行的限制,说白了就是一个核只能在同一时间运行一个线程.对于io密集型任务,python的多线程起到作用,但对于cpu密集型任务,python的多线程几乎占不到任何优势,还有可能因为争夺资源而变慢。

解决办法就是多进程和下面的协程(协程也只是单CPU,但是能减小切换代价提升性能).

25、slots

限制class实例能添加的属性

26、property

当我们需要给class实例绑定属性的时候,又希望能够检查参数,内置的装饰器@property可以将方法变成属性调用。

27、read(),readline(),readlines()的区别

read([size])方法从文件当前位置起读取size个字节,若无参数size,则表示读取至文件结束为止,它范围为字符串对象。
readline()方法从字面意思可以看出,该方法每次读出一行内容,所以,读取时占用内存小,比较适合大文件,该方法返回一个字符串对象。
readlines()方法读取整个文件所有行,保存在一个列表(list)变量中,每行作为一个元素,但读取大文件会比较占内存

28、search和match的区别

match()函数只检测字符串开头位置是否匹配,匹配成功才会返回结果,否则返回None
search()函数会在整个字符串内查找模式匹配,找到第一个匹配然后返回一个包含匹配信息的对象,该对象可以通过调用group()方法得到匹配的字符串,如果字符串没有匹配,则返回None。

29、深拷贝和浅拷贝的区别

深拷贝和浅拷贝都是对象的拷贝,都会生成一个看起来相同的对象,他们本质的却别是拷贝出来的对象的地址是否是核原对象一样,也就是是地址的的复制还是值的复制。
浅拷贝拷贝的是原对象的引用,新对象和原对象还是指向内存中同一块空间,原对象的值发生改变,会影响新对象的值。
深拷贝是再遇到可变对象,是在内部新建了一个副本,对象的值和地址都不一样。

30、map,filter, reduce,apply

filter
功能: filter的功能是过滤掉序列中不符合函数条件的元素,当序列中要删减的元素可以用某些函数描述时,就应该想起filter函数。
调用: filter(function,sequence),function可以是匿名函数或者自定义函数,它会对后面的sequence序列的每个元素判定是否符合函数条件,返回TRUE或者FALSE,从而只留下TRUE的元素;sequence可以是列表、元组或者字符串

map
功能: 求一个序列或者多个序列进行函数映射之后的值,就该想到map这个函数,它是python自带的函数,在python3.*之后返回的是迭代器,同filter,需要进行列表转换
调用: map(function,iterable1,iterable2),function中的参数值不一定是一个x,也可以是x和y,甚至多个;后面的iterable表示需要参与function运算中的参数值,有几个参数值就传入几个iterable。

reduce
功能: 对一个序列进行压缩运算,得到一个值。但是reduce在python2的时候是内置函数,到了python3移到了functools模块,所以使用之前需要 from functools import reduce
调用: reduce(function,iterable),其中function必须传入两个参数,iterable可以是列表或者元组

  • 6
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值