python 基础
q1: python深浅拷贝。
- 直接赋值:其实就是对象的引用(别名)。
- 浅拷贝(copy):拷贝父对象,不会拷贝对象的内部的子对象。
- 深拷贝(deepcopy): copy 模块的 deepcopy 方法,完全拷贝了父对象及其子对象
个人理解:若直接赋值则只是拷贝地址。若浅拷贝则只复制list, dict的地址,int, string类型则会开辟新空间赋值。若深拷贝则是递归对list,dict的子对象进行递归浅拷贝。
- 直接赋值样例:
>>> b=alist
>>> print b
[1, 2, 3, ['a', 'b']]
>>> alist.append(5)
>>> print alist;print b
[1, 2, 3, ['a', 'b'], 5]
[1, 2, 3, ['a', 'b'], 5]
- 浅拷贝样例:
>>>a = {1: [1,2,3]}
>>> b = a.copy()
>>> a, b
({1: [1, 2, 3]}, {1: [1, 2, 3]})
>>> a[1].append(4)
>>> a, b
({1: [1, 2, 3, 4]}, {1: [1, 2, 3, 4]})
- 深拷贝样例:
>>>import copy
>>> c = copy.deepcopy(a)
>>> a, c
({1: [1, 2, 3, 4]}, {1: [1, 2, 3, 4]})
>>> a[1].append(5)
>>> a, c
({1: [1, 2, 3, 4, 5]}, {1: [1, 2, 3, 4]})
q2: python闭包。
闭包就是能够读取其他函数内部变量的函数。例如在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“。在本质上,闭包是将函数内部和函数外部连接起来的桥梁。
闭包包含自由(未绑定到特定对象)变量,这些变量不是在这个代码块内或者任何全局上下文中定义的,而是在定义代码块的环境中定义(局部变量)。“闭包” 一词来源于以下两者的结合:要执行的代码块(由于自由变量被包含在代码块中,这些自由变量以及它们引用的对象没有被释放)和为自由变量提供绑定的计算环境(作用域)。
从上面两段话我们可以更好的理解:在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用。这样就构成了一个闭包。
例如:
def outer():
a = 6
def inner():
b = 8
print(a)
print(b)
return inner
if __name__ == '__main__':
res = outer()
res()
执行结果:
>>>6
>>>8
我们可以看到,当调用外部函数outer()时,会返回一个内部函数的引用res,再通过res()执行了内部函数,返回打印结果6和8。
这上面的例子中,a作为外部函数outer()的局部变量,其被分配的内存在外部函数执行后应被释放,但在外部函数执行后,发现自己的局部变量将被内部函数引用,就把这个变量绑定给了内部函数,然后再自己结束。此处的outer()的局部变量a称之为自由变量。
def outer():
a = 6
def inner():
b = 8
a += 1
print(a)
print(b)
return inner
if __name__ == '__main__':
res = outer()
res()
执行函数会报错:UnboundLocalError: local variable 'a' referenced before assignment
为了解决这个问题,我们将a转换为可变类型:
def outer():
a = [1,2,3]
def inner():
b = 8
a = [4,5]
print(a)
print(b)
return inner
if __name__ == '__main__':
res = outer()
res()
执行结果:
[4, 5]
这样就不会出问题了,但是为了让int类型也可以进行修改,所以要另外做处理,即添加nonlocal关键字。
def outer():
a = 6
def inner():
nonlocal a
b = 8
a += 1
print(a)
print(b)
return inner
if __name__ == '__main__':
res = outer()
res()
执行结果:
8
闭包的应用:
这是一个不用闭包的小例子:
class PlayerInfo():
def __init__(self, name):
self.name = name
def position(self, position):
return "{} is {}".format(self.name, position)
curry = PlayerInfo("Stephen Curry")
print(curry.position("PG"))
lbj = PlayerInfo("Lebron James")
print(lbj.position("SF"))
执行后:
Stephen Curry is PG
Lebron James is SF
添加闭包后可以简化:
def get_name(name):
def get_position(position):
return "{} is {}".format(name,position)
return get_position
if __name__ == "__main__":
player01 = get_name("Stephen Curry")
print(player01("PG"))
player02 = get_name("Lebron James")
print(player02("SF"))
q3: python的修饰函数
装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能.
装饰器的作用就是为已经存在的对象添加额外的功能。
例如:
def funA(fun):
print (fun())
def funB():
print ('B')
return 1
可以看出,这个程序的运行过程为:
1.执行函数funA,把funB当作参数传进去, print(fun()) 这一句 执行了 funB, 然后打印 ‘B’ , 返回 1
-
print(fun()) 这一句把 返回的 1 打印出来
使用装饰器后:def funA(fun): #函数本身也是对象,所以可以将函数作为参数传入另一函数并进行调用,而funB是有返回值的,所以结果输出了返回值1.(个人理解)
def funA(fun):
print (fun())
@funA
def funB():
print ('B')
return 1
output:B
没写完,继续看q3的链接