zoukankan      html  css  js  c++  java
  • 类的内置方法

    类的内置方法(魔法方法)

    一、类的内置方法

    • 什么是类的内置方法
      • 凡是在类内部定义,以__开头__结尾的方法,都是类的内置方法,也称之为魔法方法
      • 类的内置方法,会在某种条件满足下自动触发

    内置方法如下

    • __new__:在__init__触发前,自动触发。
      • 调用该类时,内部会通过__new__产生一个新的对象
    class Demo(object):
    # 条件: __new__:在__init__触发前,自动触发
        def __new__(cls, *args, **kwargs):
            print('此处是__new__方法的执行')
            # python 内部通过object调用内部的__new__实现产生一个空的对象——>内存地址
            return object.__new__(cls, *args, **kwargs)
    
    • __init__:在调用类时自动触发。
      • 通过产生的对象自动调用__init__()
        # 条件:__init__:在调用类时自动触发
        def __init__(self):
            print('此处是__init__方法的执行')
            
    demo_obj = Demo()
    此处是__init__方法的执行
    
    • __getattr__:在"对象 . 属性"获取属性时,若"属性没有"时触发
        def __getattr__(self, item):
            print('此处是__getattr__方法的执行')
            print(item)
            #return '想要返回的值'
            return '自定义的值'
    
    demo_obj = Demo()	# x
    print(demo_obj.x)	# 自定义的值
    
    • __getattribute__:在"对象 . 属性"获取属性时,无论"属性有没有"都会触发
        def __getattribute__(self, item):
            print(item)
            # print(self.__dict__)
            # return self.__dict__[item]
            # 注意:此处不能通过"对象.属性",否则会产生递归调用,程序崩溃
            # getattr:内部调用了————> __getattribute__
            return (self, item)
    

    注意:只要__getattr____getattribute__同时存在类的内部,只会触发后者

    • __setattr__当"对象 . 属性 = 属性值", 添加或修改属性时触发
        def __setattr__(self, key, value):
            print('此处是__setattr__方法的执行')
            print(key, value)
            # 出现递归
            # self.key = value
            # print(self.__dict__)
            # 此处是对 对象的名称空间——> 字典进行操作
            self.__dict__[key] = value
            
    demo_obj = Demo()	# 此处是__setattr__方法的执行
    demo_obj.x = 10		# x 10
    print(demo_obj.x)	# 10
    
    • __call__在调用对象"对象+()"时触发
        def __call__(self, *args, **kwargs):
            print('此处是__call__方法的执行')
            # 调用对象时返回的值
            return [1, 2, 3, 4, 5]
        
    demo_obj = Demo()
    res = demo_obj()	# 此处是__call__方法的执行
    print(res)			# [1, 2, 3, 4, 5]
    print(demo_obj)		# <__main__.Demo object at 0x0000028DB3DA7B38>
    
    • __str__在打印对象时触发
        def __str__(self):
            print('此处是__str__方法的执行')
            return '111'
        
    demo_obj = Demo()
    print(demo_obj)
    
    此处是__str__方法的执行
    111
    

    注意:该方法必须要有一个“字符串”返回值

    • __getitem__在对象通过“对象[key]”获取属性时触发
        def __getitem__(self, item):
            print('此处是__getitem__方法的执行')
            print(item)
            return self.__dict__[item]
        
    print(demo_obj['x'])
    print(demo_obj['y'])
    
    x
    10
    y
    20
    
    • __setitem__在对象通过“对象[key] = value值”设置属性时触发
        def __setitem__(self, key, value):
            print('此处是__setitem__方法的执行')
            print(key, value)
            # print(self.__dict__)
            # self.key = value    # {'key': value}
            # print(self.__dict__)
            self.__dict__[key] = value
            
    demo_obj['y'] = 300
    print(demo_obj.y)
    
    此处是__setitem__方法的执行
    y 300
    300
    

    二、单例模式

    • 什么是单例模式
      • 单例模式指的是在确定“类中的属性与方法”不变时,需要反复调用该类,产生不同的对象,会产生不同的内存地址,造成资源的浪费
      • 让所有类在实例化时,指向同一个内存地址,称之为单例模式
      • 无论产生多个对象,都会指向 单个 实例
    • 单例的优点
      • 节省内存空间
    class Foo:
        def __init__(self, x, y):
            self.x = x
            self.y = y
    
    foo_obj1 = Foo(10, 20)
    print(foo_obj1.__dict__)	# {'x': 10, 'y': 20}
    print(foo_obj1)	# <__main__.Foo object at 0x000002085EF77B38>
    
    foo_obj2 = Foo(10, 20)
    print(foo_obj2.__dict__)	# {'x': 10, 'y': 20}
    print(foo_obj2)	# <__main__.Foo object at 0x000002085EF77D30>
    

    这里就出现了重复调用类时,会产生不同内存地址的对象,造成资源浪费

    • 通过classmethod实现单例
    import settings
    
    
    # 通过 classmethod
    class MySQL:
        # 一个默认值,用于判断对象是否存在,对象不存在证明值是None
        # __instance = None
        __instance = None
    
        def __init__(self, host, port):
            self.host = host
            self.port = port
    
        @classmethod
        def singleton(cls, host, port):
            # 判断__instance中若没有值,证明没有对象
            if not cls.__instance:
                # 产生一个对象并返回
                obj = cls(host, port)
                # None ---> obj
                cls.__instance = obj
    
            # 若__instance中有值,证明对象已经存在,则直接返回该对象
            return cls.__instance
    
        def start_mysql(self):
            print('启动mysql...')
    
        def close(self):55555555
            
            print('关闭mysql...')
    
    
    obj1 = MySQL.singleton(settings.HOST, settings.PORT)
    print(obj1)
    obj2 = MySQL.singleton(settings.HOST, settings.PORT)
    print(obj2)
    obj3 = MySQL.singleton(settings.HOST, settings.PORT)
    print(obj3)
    

    这样产生的对象会指向同一个内存地址,会节省内存空间

    <__main__.MySQL object at 0x00000133FFB1F588>
    <__main__.MySQL object at 0x00000133FFB1F588>
    <__main__.MySQL object at 0x00000133FFB1F588>
    
    • 通过__new__实现单例
    # __new__
    class singleton:
        __instance = None
        def __new__(cls, *args, **kwargs):
            if not cls.__instance:
                cls.__instance = object.__new__(cls)
            return cls.__instance
    
    obj1 = singleton()
    obj2 = singleton()
    print(obj1)
    print(obj2)
    
    • 通过装饰器实现单例
    def singleton(cls):
        _instance = {}
        def inner(*args, **kwargs):
            if cls not in _instance:
                obj = cls(*args, **kwargs)
                _instance[cls] = obj
            return _instance[cls]
        return inner
    
    
    @singleton
    class Father:
        pass
    
    obj1 = Father()
    obj2 = Father()
    print(obj1)
    print(obj2)
    
    • 通过导入模块实现单例
    # 另写模块 SingletonCls
    class SingletonCls:
        pass
    
    obj = SingletonCls()
    
    from Singleton import obj
    print(obj)
    from Singleton import obj
    print(obj)
    from Singleton import obj
    print(obj)
    
  • 相关阅读:
    Ansible运维自动化(配置管理工具)
    Haproxy 概述及搭建
    Hadoop 单机与完全分布式配置
    大数据与Hadoop
    Hadoop 高可用
    kafka原理和集群
    zookeeper原理及搭建
    个人记录点滴
    Java中导入Excel文件
    反射相关
  • 原文地址:https://www.cnblogs.com/YGZICO/p/11959773.html
Copyright © 2011-2022 走看看