1. 深拷贝、浅拷贝
原因:
1)在对可变对象进行赋值操作时,得到的只是该对象的引用;
2)在对不可变对象进行赋值操作时,将会在内存中赋值一份拷贝副本;
3)字典、列表类型的对象为可变对象,整型、字符串、元组等类型的对象为不可变对象;
浅拷贝:
为了避免两个可变对象相互影响,需要使用python的浅拷贝
import copy
a = [1, 2, 3 ,4]
b = copy.copy(a)
a[0] = 5
print ('a:', a)
print ('b:', b)
# 运行结果
# a: [5, 2, 3, 4]
# b: [1, 2, 3, 4]
浅拷贝的原理是在内存中新建一个a的副本,然后将b指向这个副本。在使用浅拷贝后,b与a是完全独立的两个变量,列表a的变化不会对b造成任何影响。如果变量包含子对象,浅拷贝只会拷贝当前对象,不会拷贝子对象。
import copy
a = [0, 1, 2, [1, 2, 3]]
b = copy.copy(a)
a[3].append(4)
print ('a:', a)
print ('b:', b)
# 运行结果
# a: [0, 1, 2, [1, 2, 3, 4]]
# b: [0, 1, 2, [1, 2, 3, 4]]
a中包含子对象[1, 2, 3],经过浅拷贝后,b虽然与a相互独立,但为了节省空间没有复制a中的子对象,因此b中的子对象仍然是对a中子对象的引用。所以当a中子对象发生改变时也会造成b中子对象的改变。
深拷贝:
深拷贝是对原对象深层次的复制,不仅会复制对象本身,也会复制其中的子对象。深拷贝得到的对象与原对象存在于内存中不同的两个区域,两者之间是完全独立的。
import copy
a = [0, 1, 2, [1, 2, 3]]
b = copy.deepcopy(a)
a[3].append(4)
print ('a:', a)
print ('b:', b)
# 运行结果
# a: [0, 1, 2, [1, 2, 3, 4]]
# b: [0, 1, 2, [1, 2, 3]]
2. 类中的@classmethod、@staticmethod区别
Python中三种方式定义类方法:常规方法、@classmethod、@staticmethod。self通常用作实例方法的第一参数,cls通常用作类方法的第一参数,即通常用self来传递当前类对象的实例,cls传递当前类对象。
1)普通的类方法foo()需要通过self参数隐式的传递当前类对象的实例
2)@classmethod修饰的方法class_foo()需要通过cls参数传递当前类对象
3)@staticmethod修饰的方法定义与普通函数是一样的
class A(object):
def foo(self, x):
print("executing foo(%s,%s)" % (self, x))
print('self:', self)
@classmethod
def class_foo(cls, x):
print("executing class_foo(%s,%s)" % (cls, x))
print('cls:', cls)
@staticmethod
def static_foo(x):
print("executing static_foo(%s)" % x)
a = A()
- foo方法绑定对象A的实例,class_foo方法绑定对象A,static_foo没有参数绑定。
print(a.foo)
# <bound method A.foo of <__main__.A object at 0x0278B170>>
print(a.class_foo)
# <bound method A.class_foo of <class '__main__.A'>>
print(a.static_foo)
# <function A.static_foo at 0x02780390>
- foo可通过实例a调用,类对像A直接调用会参数错误;
a.foo(1)
// executing foo(<__main__.A object at 0x0278B170>,1)
// self: <__main__.A object at 0x0278B170>
A.foo(1)
// Traceback (most recent call last):
// File "<stdin>", line 1, in <module>
// TypeError: foo() missing 1 required positional argument: 'x'
但foo如下方式可以使用正常,显式的传递实例参数a。
A.foo(a, 1)
// executing foo(<__main__.A object at 0x0278B170>,1)
// self: <__main__.A object at 0x0278B170>
class_foo通过类对象或对象实例调用;
A.class_foo(1)
a.class_foo(1)
static_foo通过类对象或对象实例调用;
A.static_foo(1)
a.static_foo(1)
网友评论