python面试总结

一. python中赋值,浅拷贝,深拷贝的区别

  1. 结论
    (1)直接赋值是一个完完全全的引用,对新变量的任何改动都会影响到原对象;
    (2)浅拷贝创建了新的对象,但只是拷贝了序列的元素,对于元素也是一个序列的情况,只拷贝了对这个序列的引用
    (3)深拷贝是完完全全的拷贝,把原对象完整的拷贝到了新对象中。
  2. 例子
orig = [1, 'string', [1, 3, 5]

## 1. 赋值
copy = orig
copy[0], copy[1], copy[2][0] = 5, 'changed', 111
# 结果: copy = orig = [5, 'changed', [111, 3, 5]]
#       id[orig]=id[copy]

## 2. 浅拷贝(copy())
copy = orig.copy()
copy[0], copy[1], copy[2][0] = 5, 'changed', 111
# 结果: orig = [1, 'string', [111, 3, 5]]
#       copy = [5, 'changed', [111, 3, 5]]
#       id[orig] != id[copy]

## 3. 深拷贝(deepcopy())
copy = orig.deepcopy()
copy[0], copy[1], copy[2][0] = 5, 'changed', 111
# 结果: orig = [1, 'string', [1, 3, 5]]
#       copy = [5, 'changed', [111, 3, 5]]
#       id[orig] != id[copy]

二. python可迭代对象,迭代器和生成器

  1. 可迭代对象与迭代器的关系
    实现了__iter__的对象叫做可迭代对象(iterable)而__iter__ 的作用就是返回一个迭代器。所谓的迭代器是同时实现了__next__(返回下一个可用的元素。当没有元素时抛出StopIteration异常)和__iter__方法(返回self,即迭代器本身)
    比如我们在对一个list进行迭代时,执行的情况是:
    (1)调用可迭代对象的__iter__方法返回一个迭代器对象;
    (2)不断调用迭代器的__next__方法返回元素
    (3)当迭代完成时,抛出StopIteration异常。
  2. 迭代器与生成器的关系
    生成器其实是一种特殊的迭代器,和普通迭代器不同的是,他不需要实现__iter__和__next__方法,只需要yelid关键字,函数体没有return关键字。比如用生成器实现斐波那契数列:
def fib(max):
    n, prev, curr = 0, 0, 1
    while n < max:
        yield curr
        prev, curr = curr, curr + prev
        n += 1

三. python闭包和装饰器

  1. 闭包:
    (1)定义:在外函数中定义了一个内函数,内函数里用了外函数的临时变量,并且外函数的返回值是内函数的引用。
def outer(a):
	b = 10
	def inner():
		print(a + b)
	return inner

(2)特殊性:对于普通的函数来说,当函数生命周期结束时,会把临时变量还给内存;但是对于闭包来说,当外函数生命周期结束时,他发现自己的临时变量将会在内函数中用到,所以自己在结束的时候,再返回内函数的同时会把外函数的临时变量绑定给内函数。
(3)闭包中内函数修改外函数的局部变量:直接修改会报错。解决方法是用nonlocal关键字修饰该变量。

def outer(a):
	b = 10
	def inner():
		nonlocal b
		b += 1
		print(a + b)
	return inner

(4)闭包的作用:装饰器;实现面向对象;实现单例模式。

  1. 装饰器
    (1)基本思想:运用闭包的基本原理,对一个目标函数进行装饰。
    (2)目的:对具有不同功能的模块添加一个相同的功能。比如有两个人分别写了登录功能和注销功能,现在要测这两个功能分别要花费多长时间,简单的做法是在每一个写好的模块里面添加这个功能。但是这破坏了设计模式中的开放封闭原则(对扩展开放,对修改关闭),所以这时候就需要装饰器了。
    (3)不规范的写法:缺点是无法给目标函数传入参数和指定返回值。
def decorator(func):
	def inner():
		t1 = time.time()
		func()
		t2 = time.time()
		t = t1 - t2
		print(t)
	return inner

(4)标准写法:给内函数加上可变参数*args和关键字参数kwargs ,并加入返回值。

def decorator(func):
	def inner(*args, **kwargs):
		res = func(*args, **kwargs)
		return res
	return inner

(5)在主函数中的用法:在模块函数定义上面添加@decorator(装饰器名字)

四. python 中tuple与list的区别

  1. list可变,tuple不可变;
  2. tuple中嵌套list
    当tuple里面嵌套了一个list后,可以改变list里面元素值,例如:
t = ('a','b',['A','B'])
L = t[2]
L[0]='X'
L[1]='Y'
print(t)
##输出 ('a','b',['X','Y'])

表面上看,tuple的元素确实变了,但其实变得不是tuple的元素,而是list的元素。tuple一开始指向的list并没有改成别的list。所以tuple所谓的"不变"是说,tuple的每个元素,指向永远不变。即指向’a’,就不能改成指向’b’,指向一个list,就不能改成指向其他对象,但指向的这个list本身是可变的

  1. list中嵌套tuple
    情况与2类似,list所谓的"可变"是说,list的每个元素,指向可以改变。即指向’a’,就可以改成指向’b’,指向一个tuple,也可以改成指向其他对象,但指向的这个tuple本身是可变的

五. python 中可以作为字典key的容器

list不可以,tuple可以。从物理意义上说,在字典中要求key值是不可变的。从程序实现方面来说,list没有支持__hash__方法,tuple支持__hash__方法。

六. python 中*和**的区别

(1)*的作用:通常称作可变参数,把接收到的参数作为元组来处理;
(2)**的作用:通常称作关键字参数,把接收到的参数作为字典来处理。
例子
在这里插入图片描述
在这里插入图片描述

七. python 中is和==的区别

(1)==:比较两个对象的value是否相同;
(2)is:比较两个对象的id(内存地址)是否相同。注意的是:只有数值型字符串型的情况下,a is b才会为true;当a和b是tuple,list,dict或set型时,a is b为False。
在这里插入图片描述

八. python 中__new__和__init__的区别

在创建一个类的实例对象时,首先通过__new__(参数是cls并返回创建好的对象)用来创建实例对象,然后将创建好的实例传给了__init__函数(不能有返回值)的self参数,通过__init__初始化实例对象。
在这里插入图片描述

九. python 中类变量,类方法,实例变量,实例方法的区别

(1)实例方法可以访问实例变量(self.xxx),也可以访问类变量(初始化不在__init__函数内)
(2)类方法和实例方法的唯一区别是类方法有@classmethod装饰器修饰,与cls和self没有关系,其实可以更改cls和self,也不会报错。
(3)类方法和静态方法(@staticmethod修饰)不能访问实例变量。

十. python 中super关键字

代表父类,在子类的构造函数中使用super(subClass, self).init(),代表调用父类的构造含税,在子类的实例方法中使用super(subClass, self).fun(),代表调用父类的实例方法。

十一. python 中正则表达式

  1. 概括字符集
    在这里插入图片描述
    \d匹配数字,\D匹配非数字,\w匹配数字和字符,\W匹配非数字和字符。\s匹配空白字符(" ", “\t”, “\r”, “\n”),\S匹配非空白字符。

  2. 数量词
    在这里插入图片描述
    在这里插入图片描述

  3. 贪婪与非贪婪
    按照2中,re.findall(’[a-z]{3,6}’)进行匹配,python默认采用贪婪匹配,即采用最大数字6进行匹配。若想使用非贪婪,写法为re.findall(’[a-z]{3,6}’)

  4. 边界匹配
    在这里插入图片描述
    该问题目的是匹配出4到8位的数字,那么在原来的基础上加^(字符串的头)和$(字符串的尾)


  5. 在这里插入图片描述
    该问题目的是匹配出3个Python。

十二. python list底层实现方式

和c++ 动态数组类似,可以使用数组或者链表实现。

十三. python set去重原理

set的去重是通过两个函数__hash__和__eq__结合实现的。

  1. 当两个变量的哈希值不同时,就认为这两个变量是不同的;
  2. 当两个变量的哈希值相同时,调用__eq__方法,判断这两个值是否相等;相等则会返回true,进行去重。

十四. python 高阶函数

  1. 高阶函数的定义
    高阶函数:一个函数可以作为参数传给另外一个函数,或者一个函数的返回值为另外一个函数(若返回值为该函数本身,则为递归),满足其一则为高阶函数
  2. 三种高阶函数-map,filter和reduce
    (1)map:接收两个参数,一个函数,一个序列,其功能是使用函数对指定的序列做映射,其返回值为:python2是list,python3是map类型的的迭代器对象。
    在这里插入图片描述
    在这里插入图片描述
    注意的是:当函数参数没有返回值时,map函数将返回一个由None组成的序列。
    在这里插入图片描述
    (2)filter:接收两个参数,一个函数,一个序列,其主要功能是过滤。其返回值为:python2是list,python3是filter类型的的迭代器对象。
    在这里插入图片描述
    注意的是:当函数参数没有返回值时,filter函数将返回一个空的序列。
    在这里插入图片描述
    (3)reduce:接收两个参数,一个函数,一个序列,其主要功能是累加或累乘,返回值为一个整数。
    在这里插入图片描述
    注意的是:当函数参数没有返回值时,reduce函数不返回任何值。

十五. python的lambda函数

【参考1】【参考2】
lambda函数也叫匿名函数,即函数没有具体的名称。

lambda语句构建的是一个函数对象,匿名函数有个限制,就是只能有一个表达式,不用写return,返回值就是该表达式的结果。

特点:

  1. lambda只是一个表达式,使用lambda可以省去定义函数的过程,让代码更加精简。
  2. lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。
  3. lambda函数拥有自己的命名空间,且不能访问自有参数列表之外或全局命名空间里的参数。
  4. 虽然lambda函数看起来只能写一行,却不等同于C或C++的内联函数,后者的目的是调用小函数时不占用栈内存从而增加运行效率。

语法(lambda函数的语法只包含一个语句):

lambda [arg1 [,arg2,.....argn]]:expression

例如:

sum = lambda arg1, arg2: arg1 + arg2
print(sum( 10, 20 ))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值