写给小白的Python之016:面向对象-魔法方法

导读:

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

猜你喜欢

转载自www.cnblogs.com/salmond/p/9000351.html
今日推荐