导读:
1. __init__方法
2. __str__、__repr__方法
3. __del__方法
4. __new__方法
魔法方法:在恰当的时候会自动执行的方法。
- 魔法方法名两边各有2个下划线。
- 方法名称都已经由官方规定好了的。
1. __init__方法
在创建实例时,通常可能都需要有特定的初始状态,所以一个类可以定义一个名为 __init__() 的特殊方法(构造函数):
def __init__(self):
self.data = []
__init__()在创建对象(类的实例化)之后自动执行。用于初始化对象的属性。
过程:定义类->创建对象->执行__init__方法->赋值给对象名。
__init__不能显式地return一个值,因为它默认返回None。
在类的方法里定义属性的固定值,则每个对象实例变量的属性值都是相同的。__init__方法能让实例化的每个对象,都有不同的属性值。
在__init__(self)中定义好形参,实例化对象时,传入实参。
def __init__(self, name, skill):
""" __init__() 方法,用来做变量初始化 或 赋值 操作"""
self.name = name
self.skill = skill
一个类中的多个对象,每个对象的属性是各自保存的,都有各自独立的地址;
但是实例方法是所有对象共享的,只占用一份内存空间。类会通过self来判断是哪个对象调用了实例方法。
2. __str__、__repr__方法
__str__方法
__str__()在打印对象时自动执行。用于返回一个字符串,作为对象的描述信息。
该方法只有self一个参数,必须要有返回值,且返回值必须为字符串类型,当在类的外包部print(对象)则打印这个返回值。如果没有__str__(),则默认打印 对象在内存的地址。
class Student(object): def __init__(self, name): self.name = name def __str__(self): return "%s 是最帅的!" % self.name print(Student('salmond')) # 输出__str__方法返回的内容 Student('salmond') # 输出内存地址
__repr__方法
__str__()返回用户看到的字符串,而__repr__()返回程序开发者看到的字符串,也就是说, __repr__()是为调试服务的。
Student('salmond') 输出的是内存地址,如何让它显示内容呢?解决办法是再定义一个__repr__()。但是通常__str__()和__repr__()代码都是一样的,所以,有个偷懒的写法:
class Student(object): def __init__(self, name): self.name = name def __str__(self): return 'Student object (name=%s)' % self.name __repr__ = __str__ s = Student('salmond') print(s)
3. __del__方法
当对象被销毁时,自动调用。用于验证对象是否被销毁、释放资源(关闭文件)等。
class Hero(object): def __init__(self, name): print('__init__方法被调用') self.name = name def __del__(self): print("__del__方法被调用") print("%s 被 GM 干掉了..." % self.name) taidamier = Hero("泰达米尔") # 创建对象 print("%d 被删除1次" % id(taidamier)) del(taidamier) # 删除对象 print("--" * 10) gailun = Hero("盖伦") # 内存地址 gailun1 = gailun # 内存地址同上 gailun2 = gailun # 内存地址同上 print("%d 被删除1次" % id(gailun)) del(gailun) print("%d 被删除1次" % id(gailun1)) del(gailun1) print("%d 被删除1次" % id(gailun2)) del(gailun2) # 当引用计数为0时,才会调用__del__方法
总结:
1. 当有变量保存了一个对象的引用时,此对象的引用计数就会加1;
2. 当使用del() 删除变量指向的对象时,则会减少对象的引用计数。如果对象的引用计数不为1,那么会让这个对象的引用计数减1,当对象的引用计数为0的时候,则对象才会被真正删除(内存被回收)。
4.__new__方法
当我们创建一个类的实例时,类会先调用 __new__(cls[, ...]) 来创建实例,然后__init__ 方法再对该实例(self)进行初始化。
一般情况下,我们不需要重载 __new__ 方法。但在某些情况下,我们想控制实例的创建过程,这时可以通过重载 __new_ 方法来实现。
# __new__和__init__的作用,重载 __new__ 方法 class A(object): def __init__(self): print(self) # <__main__.A object at 0x000001DB1C0B7828> print("这是 init 方法") # 这是 init 方法 def __new__(cls): print(id(cls)) # 2040549602280 print("这是 new 方法") # 这是 new 方法 ret = object.__new__(cls) print(ret) # <__main__.A object at 0x000001DB1C0B7828> return ret print(id(A)) # 2040549602280 A()
总结:
- _ 重载 __new__ 方法,需要返回类的实例;因此,__new__至少要有一个参数cls,代表要实例化的类,此参数在实例化时由Python解释器自动提供。
- _ __new__必须要有返回值,返回实例化出来的实例,这点在自己实现__new__时要特别注意,可以return父类__new__出来的实例,或者直接是object的__new__出来的实例。
- _ __init__有一个参数self,就是这个__new__返回的实例,__init__在__new__的基础上可以完成一些其它初始化的动作,__init__不需要返回值。
- _ 我们可以将类比作制造商,__new__方法就是前期的原材料购买环节,__init__方法就是在有原材料的基础上,加工,初始化商品环节。
- _ __new__ 是在 __init__ 之前被调用的;
- _ __new__ 是类方法, __init__ 是实例方法;
重载__new__示例:
class A(object): __dict = dict() def __new__(cls): if 'key' in A.__dict: print('EXISTS') return A.__dict['key'] else: print('NEW') return object.__new__(cls) def __init__(self): print('INIT') A.__dict['key'] = self >>> a1 = A( ) NEW INIT >>> a2 = A( ) EXISTS INIT >>> a3 = A( ) EXISTS INIT