四时宝库

程序员的知识宝库

Python中关于魔法方法、单例模式的知识

目录:

init,del,add,str和 repr,call,单例模式,class,dict,doc,bases,mro


魔法方法:

定义:在特定条件下,触发方法

在python里面很多以双下划线开头且结尾的固定方法,他们会在特定时机被触发执行

例子:__init__


__init__ ------构造函数

__init__为初始化魔法方法,又叫构造函数,因为在初始化时,可以构造属性

触发条件:在实例化后自动调用,以完成实例初始化



__del__ ------ 析构函数

__del__是析构函数,用来回收内存(释放内存空间)

主动触发__del__:

触发条件:del,当使用del删除对象时,会调用他本身的析构函数。


自动触发__del__:

析构函数会当对象在某个作用域中调用完毕,在跳出其作用域的同时析构函数也会被调用一次,这样可以用来释放内存空间。


**析构函数不会立即触发回收机制**

class Demo():

    def __init__(self):
        self.age = 18

    def __del__(self):
        print('del被调用')

x = Demo()
y = Demo()
del x               #主动触发__del__
print(y.age)

del被调用 #主动触发__del__

18 #先运行__init__

del被调用 #自动触发__del__;先运行其他魔法方法,再自动触发del。析构函数 不会立即触发回收机制


__add__------ 定义加法的行为:+

__ add__(self, other) 触发条件:x+y (相当于self+other)



__str__和__ repr__

含义:
__ str__(self):定义当被 str() 调用或者打印对象时的行为   
__ repr__(self):定义当被 repr() 调用或者直接执行对象时的行为            

触发条件:
__str__: 输出实例对象变量的时候触发, 在非交互模式下, 如果二者同时存在, 只会触发__str__
__repr__ : 输出实例对象变量的时候触发, 在交互式模式下, 如果二者同时存在, 
 输出不使用print, 只会触发__repr__;若使用print,只能触发__str__

 **这两个魔法方法在定义时需使用return,而不能使用print**





__call__------实例后像函数一样调用时触发

触发条件:变量名() ---- 类似函数的调用方法


单例模式------实现数据互通

  • 如何实现数据互通?

分析:

1. 实例对象与实例对象数据不互通,这是因为每次实例化时,生成了新的实例对象,每一个实例对象都是类的独一无二的个体

2. 因此要想实现数据互通,就需要引用同一个实例对象

3. 此时,我们就需要知道创建实例对象的方法,__new__魔法方法可以实现这个功能

#__new__(cls, *args, **kwargs): 用来创建实例对象; 它返回的值:类的实例化对象

# cls:类本身


__new__和__init__的执行顺序:

__new__:创建实例化对象

__init__:初始化


要先创建实例化对象,才能执行初始化,因为执行初始化的对象是实例本身;

因此先执行__new__,再执行__init__

注意:在定义__new__方法时,一定要返回(return)实例对象,这样才能执行__init__



以下是:在定义__new__方法时,return实例对象

class Demo():
    def __init__(self,length,width):
        print('触发init魔法方法')    
        self.length = length
        self.width = width

    def __new__(cls, *args, **kwargs):
        print('触发new魔法方法')

        return object.__new__(cls)
 #object是所有类的超类,可以理解为是所有类的祖先
 #__new__是创建实例对象的魔法方法
 #这里通过Demo类的祖先来创建Demo类的实例对象,即object.__new__,并返回实例对象,
这样才可以调用__init__魔法方法

x = Demo(1,2)
print(x)            #生成了实例对象
print(x.length)     #调用__init__,输出x实例对象的length属性

触发new魔法方法

触发init魔法方法 #先执行__new__,再执行__init__

<__main__.Demo object at 0x00000000027D7788> #生成了实例对象

1 #输出x实例对象的length属性


  • 在单例模式下添加属性:

添加属性之前,首先要判断要添加的属性是否在当前类里存在:

hasattr(查询的类, 属性名):查找属性,判断类的某个属性是否存在

class Demo():
    def __init__(self,length,width):
        self.length = length
        self.width = width

    def __new__(cls, *args, **kwargs):
        if not hasattr(cls,'instance'):
        # 判断instance这个属性是否不存在Demo类里,为真,则进行if not下的操作
        #cls改成Demo也可以,因为是在Demo类中查找instance属性

            cls.instance = super().__new__(cls)
            #属性名 = 实例对象(属性值)
            #通过继承超类(父类),来创建类的实例对象;
            #super是继承超类的方法,__new__是创建实例对象的魔法方法

        return cls.instance
        #最后返回属性instance


x = Demo(1,2)     #用x变量接收实例对象
y = Demo(3,3)     #用y变量接收实例对象

x.instance = 1    #添加instance的属性值
y.instance = 10   #添加instance的属性值
# 因为在单例模式下,数据实现互通,因此x和y接收的都是同一个实例对象,
所以y.instance的属性值10,覆盖了之前的x.instance的属性值1

print(x.instance)
print(y.instance)    #不管打印x还是y变量,返回的值都以最后的instance属性值为准

10

10


__class__ ------- 查看类名

触发条件:实例.__class__

class Demo():
    pass

x = Demo()
print(x.__class__)

<class '__main__.Demo'> ----表示x的类名是Demo


__dict__-------查看实例对象的全部属性

触发条件:实例.__dict__

输出:以字典形式输出属性和值

class Demo():
    def __init__(self):
        self.age = 18

x = Demo()
x.name = 'x'
x.sex = '男'
print(x.__dict__)

{'age': 18, 'name': 'x', 'sex': '男'}


__doc__--------查看对象注释信息

触发条件:实例/类名.__doc__

class Demo():
    '''
    测试
    '''
    def __init__(self):
        self.age = 18

x = Demo()
print(x.__doc__)              #实例.__doc__
print(Demo.__doc__)      #类名.__doc__

测试


测试


__bases__--------查看类的父类

触发条件:类名.__bases__

class Demo():

    def __init__(self):
        self.age = 18

print(Demo.__bases__)

(<class 'object'>,)


__mro__-------- 多继承情况下, 查看继承顺序

触发条件:类名.__mro__

class Demo():

    def __init__(self):
        self.age = 18

print(Demo.__mro__)

(<class '__main__.Demo'>, <class 'object'>)

----先返回自己的类,再返回比自己更高级的父类,任何类最终都会返回object


__class__和__bases__,__mro__可以一起用,因为【实例.__class__】表示类名

class Demo():

    def __init__(self):
        self.age = 18

x = Demo()
print(x.__class__.__bases__)
print(x.__class__.__mro__)

(<class 'object'>,)

(<class '__main__.Demo'>, <class 'object'>)

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言
    友情链接