• Python基础: 双下方法


    1、双下方法

    定义:双下方法是特殊方法,它是解释器提供的 由双下划线加方法名加双下划线 方法名的具有特殊意义的方法,双下方法主要是python源码程序员使用的,我们在开发中尽量不要使用双下方法,但是深入研究双下方法,更有益于我们阅读源码。

    (1)调用:不同的双下方法有不同的触发方式,

    <1> __ len__ -- len() 触发

    class A(object):
    
        def __init__(self,name):
            self.name = name
            print("触发了__init__")
    
        def __len__(self):     # len() 触发
            print("走这里")
            return len(self.name)    # return len("xqrqwr")  str中__len__
            # 必须有返回值,返回值的类型必须是整型
    
    a = A("xqrqwr")
    print(len(a))
    
    # str
    a = "12345"      # str这个类的实例
    lst = [1,2,3,4,4,5,5,5,5] # list这个类的实例
    print(len(a))
    print(len(lst))
    

    <2> __ hash__ --hash() 触发

    class A(object):
    
        def __init__(self,name,age):
            self.name = name
            self.age = age
    
        def __hash__(self):  # hash()
            hash({1,2,345})  # 可变数据类,不可数据类型
            return 1
            # 必须有返回值,返回值的类型必须是整型
    
    a = A("meet",25)
    print(hash(a))
    

    <3> __ str__ --print 或者 str() 触发

    class A:
    
        def __init__(self,name,age,sex):
            self.name = name
            self.age = age
            self.sex = sex
    
        def __str__(self):   # print 触发 str()
            print(111)
            return f"姓名:{self.name} 年龄:{self.age} 性别:{self.sex}"
            # 必须有返回值,返回值的类型必须是字符串
    
    
    a = A("mee",20,"男")
    a1 = A("mee1",200,"男1")
    str(a)
    print(a)
    print(a1)
    
    
    # 以下对比:
    a = A("mee",20,"男")
    a1 = A("mee2",200,"女")
    
    print(f"姓名:{a.name} 年龄:{a.age} 性别:{a.sex}")   # "姓名:meet 年龄:20 性别:男"
    print(f"姓名:{a1.name} 年龄:{a1.age} 性别:{a1.sex}")  # "姓名:meet2 年龄:200 性别:女"
    

    <4> __ repr__ --print 或者 %r 触发

    class A:
    
        def __init__(self):
            pass
    
    
        def __repr__(self):   # print触发  %r
            print(1111)
            return "天魔"
    
        def __str__(self):   # str 优先级高于 repr  两个都存在就只执行str
            return "小元"
    
    a = A()
    print("%r"%(a))
    

    <5> __ call__ --对象调用时触发,对象后加括号即:对象() 或者 类()()

    class A:
    
        def __init__(self):
            pass
    
        def __call__(self, *args, **kwargs):  # 对象()时调用的__call__
            print("走我")
            print(*args, **kwargs)
    
    a = A()
    a()
    

    <6> __ eq__ 等于

    class A(object):
    
        def __init__(self,name,age):
            self.name = name
            self.age = age
    
        def __eq__(self, other):     #  a == a1
            if self.name == other.name:
                return True
            else:
                return False
    
    a = A("mee",56)
    a1 = A("mee",108)
    
    print(a == a1)
    

    <7> __ del__ 构造方法,当对象在内存中被释放时,自动触发执行

    ​ 此方法一般情况下无需定义,因为python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为内存的分配和释放都是交给python解释器类执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。

    class A:
        def __init__(self):
            pass
    
        def __del__(self):    del 触发
            print("删除时执行我")
    
    a = A()
    
    import time
    time.sleep(5)
    del a
    
    a = 1
    b = a
    a = b
    

    垃圾回收机制:

        # 80  5/s
        # 引用计数
        # 标记清除
        # 分袋回收 袋一:10 2/h  袋二: 5/3 4h  袋三: 3 20h
    

    <8> __ item__ 系列 可以像操作字典一样操作实例方法

    dic["键"] = 值
    del dic["键"]
    dic["键"]
    

    class A:
    
        def __init__(self,name,age):
            self.name = name
            self.age = age
    
        def __getitem__(self, item):
            print(self.__dict__)
            print(self.__dict__[item])  # self.__dict__ 获取的就是字典
    
        def __setitem__(self, key, value):
            self.__dict__[key] = value
    
        def __delitem__(self, key):
            del self.__dict__[key]
    
    a = A("meet",58)
    a["sex"] = "男"
    a["sex"]
    del a["sex"]
    print(a.__dict__)
    

    <9> __ new__ 单例模式(工厂模式)

    ​ 单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例类的特殊类。通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。

    class A(object):
    
        def __init__(self,name):  # 初始化
            self.name = name
            print("我是__init__,先走我")
    
        def __new__(cls, *args, **kwargs):
            print("我是__new__,先走我")
            return "啦啦啦"
    
    a = A("meet")
    print("我是谁:",a)
    

    '''
    遇到问题没人解答?小编创建了一个Python学习交流QQ群:579817333 
    寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
    '''
    class A(object):
    
        def __init__(self,name):  # 初始化
            self.name = name
            print("我是__init__,先走我")
    
        def __new__(cls, *args, **kwargs):
            obj = object.__new__(A)
            print("我在哪:",obj)
            return obj                   # obj == __init__()
    
    a = A("meet")
    print("我是谁:",a)
    

    class A(object):
    
        def __init__(self,name): # 初识化
            self.name = name
    
    
        def __new__(cls, *args, **kwargs):
            obj = object.__new__(A)   # 调用的是object类中的__new__ ,只有object类中的__new__能够创建空间
            return obj   #本质: obj == __init__()     return __init__()  # 触发了__init__方法
    
    
    a = A("mee")  # a是对象的内存地址
    a1 = A("天魔")  # a是对象的内存地址
    a2 = A("天阳")  # a是对象的内存地址
    print(a.name)
    print(a1.name)
    print(a2.name)
    

    # 先执行__new__方法再执行__init__方法
    class A:
        __a = None  #__a =  0x000001F346079FD0
    
        def __init__(self,name,age):
            self.name = name
            self.age = age
    
        def __new__(cls, *args, **kwargs):
            if cls.__a is None:
                obj = object.__new__(cls)
                cls.__a = obj
            return cls.__a
    
    a = A("mee",123)  # 地址0x000001F346079FD0
    a1 = A("天魔",11)
    print(a.name)
    print(a1.name)
    

    单例模式:不管创建多少次,使用的都是同一个内存空间

    模块的导入,手写的单例模式

    实例化对象时发生的事:

    创建对象,并开辟对象空间 __ next__

    自动执行 __ init方法,隐性的将对象地址传给self

    将对象属性封装到对象空间

    2、上下文

    (1)__ enter__

    (2)__ exit__

    class my_open:
    
        def __init__(self,file,mode="r",encoding="utf-8"):
            self.file = file
            self.mode = mode
            self.encoding = encoding
    
        def __enter__(self):
            self.f = open(self.file,self.mode,encoding=self.encoding)
            return self.f
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            print(exc_type,exc_val,exc_tb) # 没有错误时就是None
            self.f.close()
    
    
    with my_open("a.txt") as ffff:
        for i in ffff:
            print(i)
    print(ffff.read(1111))
    print(ffff.read())
    
  • 相关阅读:
    linux挂载windows共享文件夹
    centos-6.7 内核升级(转)
    关闭系统邮件提醒:you hava a new mail(转)
    2016年国内开源镜像站点汇总(转)
    RedHat/Fedora/Centos 下bash 自动补全命令
    shell死循环脚本示例
    查看http的并发请求数与其TCP连接状态
    (十二)微信小程序实现登陆页面+登陆逻辑
    vue实现登陆单页面
    vue前端项目初始化的步骤
  • 原文地址:https://www.cnblogs.com/djdjdj123/p/12740763.html
Copyright © 2020-2023  润新知