1 浅拷贝与深拷贝
数据有嵌套结构时,浅拷贝与深拷贝开辟独立内存的级别不同。
例如数据:li=[1,2,[3,4]]
。该数据有两层结构。
浅拷贝copy.copy():只给外层结构,开辟独立内存。(即只有外层结构内存独立,内层内存由复制品和原件共享)
深拷贝copy.deepcopy():给所有层,全部开辟独立内存。(即各层内存都独立)
示例:
import copy
a1 = [1,2,[3,4]]
b1 = copy.copy(a1)
b1[0] = 'changed1'#第一个改变的地方
b1[2][0]='changed2'#第二个改变的地方
a2 = [1,2,[3,4]]
b2 = copy.deepcopy(a2)
b2[0] = 'changed1'
b2[2][0] = 'changed2'
print(a1)
print(b1,'\n')
print(a2)
print(b2,'\n')
输出:
[1, 2, ['changed2', 4]]
['changed1', 2, ['changed2', 4]] #外层开辟了独立内存,所以复制品的外层变化时,原件的外层不会变。
#内层没有开辟独立内存,所以内层的内存由复制品和原件共享。
[1, 2, [3, 4]]
['changed1', 2, ['changed2', 4]] #全部层都开辟了独立内存,所以复制品的变化,不会影响到原件。
2 copy() & deepcopy()
常见的有三种用法:
import copy
object.copy()
copy.copy()
copy.deepcopy()
常见的用法有三种,但实际方法只有两种:copy()
和deepcopy()
。其中,object.copy() == copy.copy()
。
示例1,由下面的例子可以看出object.copy() 就是 copy.copy(),copy()方法是浅拷贝,deepcopy()是深拷贝。
import copy
a1 = [1,2,[3,4]]
b1 = a1.copy()
a2 = [1,2,[3,4]]
b2 = copy.copy(a2)
a3 = [1,2,[3,4]]
b3 = copy.deepcopy(a3)
b1[2][0] = 'changed'
b2[2][0] = 'changed'
b3[2][0] = 'changed'
print(a1)
print(b1,'\n')
print(a2)
print(b2,'\n')
print(a3)
print(b3)
输出:
[1, 2, ['changed', 4]]
[1, 2, ['changed', 4]]
[1, 2, ['changed', 4]]
[1, 2, ['changed', 4]]
[1, 2, [3, 4]]
[1, 2, ['changed', 4]]
3 命名空间 LEGB
参考网址:Python LEGB规则
Python在命名空间中查找变量时,遵循LEGB规则。即LEGB规则规定了Python查找变量的顺序:
- L— Local:函数内部
- E—Enclosing Function local :嵌套函数内部
- G—global:当前模块内部
- B—builtin:内建模块
LEGB规则规定的查找名称顺序:local–>enclosing function locals–>global–>builtin。
举例:
x = 1
def foo():
x = 2
def innerfoo():
x = 3
print 'locals ', x
innerfoo()
print 'enclosing function locals ', x
foo()
print 'global ', x
locals 3
enclosing function locals 2
global 1
稍加改动:
x = 1
def foo():
x = 2
def innerfoo():
# x = 3 #此处改动:注释掉
print 'locals ', x
innerfoo()
print 'enclosing function locals ', x
foo()
print 'global ', x
locals 2
enclosing function locals 2
global 1
可以发现:当注释掉x = 3以后,函数innerfoo内部查找到的x是x = 2。
在上述两个例子中,从内到外,依次形成四个命名空间:
def innerfoo()::Local, 即函数内部命名空间;
def foo()::Enclosing function locals;外部嵌套函数的名字空间
module(文件本身):Global(module);函数定义所在模块(文件)的名字空间
Python内置模块的名字空间:Builtin
x = 3 属于函数内部命名空间,当被注释掉之后,函数innerfoo内部通过print x 使用x这个名称时,触发了名称查找动作。
首先在Local命名空间查找,没有找到,然后到Enclosing function locals命名空间查找,查找成功,然后调用。
4 Python 私有、保护、共有、系统定义
_ _ foo_ _ :特殊方法,系统定义名字,例如__init__,new,del。
_ _foo :私有(private),只有类自己可以访问,不能用于 from module import *。Python的private与Java、C++中的不太相同,Python中的私有方法只是为了防止子类修改,但是子类仍可以通过_classname _ _ foo来访问,即“单下划线”+类名。
_foo:保护(protect),只有类和其子类可以访问。
foo:公开(public),都可以访问。
记忆方法:保护性越强,写起来越麻烦。2333~