zoukankan      html  css  js  c++  java
  • 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("cai")  str中__len__
            # 必须有返回值,返回值的类型必须是整型
    
    a = A("cai")
    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("cai",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("cai",20,"男")
    a1 = A("cai1",200,"男1")
    str(a)
    print(a)
    print(a1)
    
    
    # 以下对比:
    a = A("cai",20,"男")
    a1 = A("cai2",200,"女")
    
    print(f"姓名:{a.name} 年龄:{a.age} 性别:{a.sex}")   # "姓名:cai 年龄:20 性别:男"
    print(f"姓名:{a1.name} 年龄:{a1.age} 性别:{a1.sex}")  # "姓名:cai2 年龄:200 性别:女"
    

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

    class A:
    
        def __init__(self):
            pass
    
    
        def __repr__(self):   # print触发  %r
            print(1111)
            return "cai"
    
        def __str__(self):   # str 优先级高于 repr  两个都存在就只执行str
            return "yong"
    
    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("cai",56)
    a1 = A("cai",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("cai",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("cai")
    print("我是谁:",a)
    
    
    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("cai")
    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("cai")  # a是对象的内存地址
    a1 = A("yong")  # a是对象的内存地址
    a2 = A("liang")  # 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("cai",123)  # 地址0x000001F346079FD0
    a1 = A("cai1",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())
    
    
  • 相关阅读:
    synchronized 到底该不该用?
    线上Java程序占用 CPU 过高,请说一下排查方法?
    『JVM』我不想知道我是怎么来滴,我就想知道我是怎么没滴
    Golang 实现 Redis(8): TCC分布式事务
    Golang 实现 Redis(7): 集群与一致性 Hash
    Golang 实现 Redis(6): 实现 pipeline 模式的 redis 客户端
    LSM 树详解
    uni-app subNVue 原生子窗体简单使用案例(app端)
    日计不足涓滴成河-自定义响应结果格式化器
    RTT之软件包
  • 原文地址:https://www.cnblogs.com/caiyongliang/p/11716430.html
Copyright © 2011-2022 走看看