一. python中赋值,浅拷贝,深拷贝的区别
- 结论
(1)直接赋值是一个完完全全的引用,对新变量的任何改动都会影响到原对象;
(2)浅拷贝创建了新的对象,但只是拷贝了序列的元素,对于元素也是一个序列的情况,只拷贝了对这个序列的引用;
(3)深拷贝是完完全全的拷贝,把原对象完整的拷贝到了新对象中。 - 例子
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可迭代对象,迭代器和生成器
- 可迭代对象与迭代器的关系
实现了__iter__的对象叫做可迭代对象(iterable)而__iter__ 的作用就是返回一个迭代器。所谓的迭代器是同时实现了__next__(返回下一个可用的元素。当没有元素时抛出StopIteration异常)和__iter__方法(返回self,即迭代器本身)
比如我们在对一个list进行迭代时,执行的情况是:
(1)调用可迭代对象的__iter__方法返回一个迭代器对象;
(2)不断调用迭代器的__next__方法返回元素
(3)当迭代完成时,抛出StopIteration异常。 - 迭代器与生成器的关系
生成器其实是一种特殊的迭代器,和普通迭代器不同的是,他不需要实现__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)定义:在外函数中定义了一个内函数,内函数里用了外函数的临时变量,并且外函数的返回值是内函数的引用。
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)基本思想:运用闭包的基本原理,对一个目标函数进行装饰。
(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的区别
- list可变,tuple不可变;
- 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本身是可变的
- 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 中正则表达式
-
概括字符集
\d匹配数字,\D匹配非数字,\w匹配数字和字符,\W匹配非数字和字符。\s匹配空白字符(" ", “\t”, “\r”, “\n”),\S匹配非空白字符。 -
数量词
-
贪婪与非贪婪
按照2中,re.findall(’[a-z]{3,6}’)进行匹配,python默认采用贪婪匹配,即采用最大数字6进行匹配。若想使用非贪婪,写法为re.findall(’[a-z]{3,6}?’) -
边界匹配
该问题目的是匹配出4到8位的数字,那么在原来的基础上加^(字符串的头)和$(字符串的尾) -
组
该问题目的是匹配出3个Python。
十二. python list底层实现方式
和c++ 动态数组类似,可以使用数组或者链表实现。
十三. python set去重原理
set的去重是通过两个函数__hash__和__eq__结合实现的。
- 当两个变量的哈希值不同时,就认为这两个变量是不同的;
- 当两个变量的哈希值相同时,调用__eq__方法,判断这两个值是否相等;相等则会返回true,进行去重。
十四. python 高阶函数
- 高阶函数的定义
高阶函数:一个函数可以作为参数传给另外一个函数,或者一个函数的返回值为另外一个函数(若返回值为该函数本身,则为递归),满足其一则为高阶函数 - 三种高阶函数-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,返回值就是该表达式的结果。
特点:
- lambda只是一个表达式,使用lambda可以省去定义函数的过程,让代码更加精简。
- lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。
- lambda函数拥有自己的命名空间,且不能访问自有参数列表之外或全局命名空间里的参数。
- 虽然lambda函数看起来只能写一行,却不等同于C或C++的内联函数,后者的目的是调用小函数时不占用栈内存从而增加运行效率。
语法(lambda函数的语法只包含一个语句):
lambda [arg1 [,arg2,.....argn]]:expression
例如:
sum = lambda arg1, arg2: arg1 + arg2
print(sum( 10, 20 ))