zoukankan      html  css  js  c++  java
  • 类中的内置方法(魔法方法、双下方法)

    __len__

    class A:
        def __init__(self,name):
            self.name=name
        def __len__(self):
            return len(self.name)
    liu=A("liulin")  #实例化
    print(len(liu)) #调用类中的__len__() 方法,如果类中没有__len__(),则报错

    __eq__

    等号比较,定制返回值:==  自动触发

    class A:
        def __init__(self,name,cls,age,sex):
            self.name = name
            self.cls = cls
            self.age = age
            self.sex = sex
    lin = A('','1班',18,'')
    lin2 = A('','1班',18,'')
    print(lin==lin2)  #返回False,因为比较的是内存地址,值一样,地址不一样
    class A:
        def __init__(self,name,cls,age,sex):
            self.name = name
            self.cls = cls
            self.age = age
            self.sex = sex
        def __eq__(self, other):        #在类中定义一个__eq__():方法,只要用==比较,一定执行此函数
            if self.__dict__ == other.__dict__:   #如果值相等
                return True
            else:
                return False
    lin = A('小黑','py10期',18,'')
    lin2 = A('小黑','py10期',18,'')
    print(lin==lin2)    #返回True
    让上段代码返回True
    class A:
        def __init__(self,name,cls,age,sex):
            self.name = name
            self.cls = cls
            self.age = age
            self.sex = sex
        def __eq__(self, other):        #在类中定义一个__eq__():方法,只要用==比较,一定执行此函数
                return True           #只要比较,一定返回True
    lin = A('','1',18,'')
    lin2 = A('','2',19,'')
    print(lin==lin2)    #返回True
    值不一样也可以返回(True) 定制返回值

    __format__

    定制输出格式

    format_dict={
        'nat':'{obj.name}-{obj.addr}-{obj.type}',#学校名-学校地址-学校类型
        'tna':'{obj.type}:{obj.name}:{obj.addr}',#学校类型:学校名:学校地址
        'tan':'{obj.type}/{obj.addr}/{obj.name}',#学校类型/学校地址/学校名
    }
    class School:
        def __init__(self,name,addr,type):
            self.name=name
            self.addr=addr
            self.type=type
    
        def __format__(self, format_spec):
            return format_spec.format(obj=self)
    
    s1=School('成栋','北京','私立') #实例化  三个属性
    print(format(s1,format_dict['tna'])) #把对象和定制的格式传进去
    print(format(s1,format_dict['nat']))
    print(format(s1,format_dict['tan']))
    '''输出:
    私立:成栋:北京
    成栋-北京-私立
    私立/北京/成栋
    '''

    __str__

    class Person:
        def __init__(self,name,age):
            self.name=name
            self.age=age
    liulin=Person('刘林',25)
    print(liulin)  #直接打印对象 <__main__.Person object at 0x00000194EC747DA0>
    
    ----------------------------------------------------------------
    #如果想返回属性
    class Person:
        def __init__(self,name,age):
            self.name=name
            self.age=age
        def __str__(self):
            return str(self.__dict__)  #返回的必须是字符串,否则报错
    liulin=Person('刘林',25)
    print(liulin)  #直接打印对象就可以打印出结果:{'name': '刘林', 'age': 25}
    print(str(liulin))
    print("%s"%liulin) 三个结果一样

    __repr__

    class Person:
        def __init__(self,name,age):
            self.name=name
            self.age=age
        def __str__(self):
            return str(self.__dict__)  #返回的必须是字符串,否则报错
        def __repr__(self):
            return "repr:Person中的repr对象"
    liulin=Person('刘林',25)
    print(str(liulin))            #  {'name': '刘林', 'age': 25}
    print(repr(liulin))           #repr:Person中的repr对象
    print("%s"%liulin)            #{'name': '刘林', 'age': 25}
    print("%r"%liulin)            #repr:Person中的repr对象
    class Person:
        def __init__(self,name,age):
            self.name=name
            self.age=age
        def __repr__(self):
            return "repr:Person中的repr对象"
    liulin=Person('刘林',25)
    print(str(liulin))
    print(repr(liulin))
    print("%s"%liulin)
    print("%r"%liulin)            #所有值都是   repr:Person中的repr对象
                                   #当类中没有__str__方法时,调用str   会自动执行repr中的代码
    当类有repr,没有str时
    class Person:
        def __init__(self,name,age):
            self.name=name
            self.age=age
        def __str__(self):
            return str(self.__dict__)  #返回的必须是字符串,否则报错
    liulin=Person('刘林',25)
    print(str(liulin))            #  {'name': '刘林', 'age': 25}
    print(repr(liulin))           #<__main__.Person object at 0x0000015D043A7EF0>
    print("%s"%liulin)            #{'name': '刘林', 'age': 25}
    print("%r"%liulin)            #<__main__.Person object at 0x0000015D043A7EF0>
    当类中有str,没有repr时

    总结:当类中有__str__没有__repr__ ,则调用str可以执行,调用repr返回内存地址

               当类中有__repr__没有__str__,则调用str和repr,都执行repr方法中的代码

       两个都有,各走各的

    __del__

    析构方法,当对象在内存中被释放时,自动触发执行。

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

    # 构造方法 创建一个对象的
    # 初始化方法 __init__ 给已经创建出来的对象添加属性
    # 析构方法 删除一个对象的时候调用的方法
    import time
    class A:
        def __init__(self):
            self.f = open('userinfo','a')
        def consume(self):
            pass
        def __del__(self):
            '''在删除一个对象之前做一些收尾工作'''
            self.f.close()
            print('删除一个对象的时候调用我')
    a = A()
    time.sleep(1)
    del a
    # 删除一个对象的时候,如果内部存在__del__方法,
    # 那么在删除一个对象之前先执行__del__方法中的代码

    __new__  构造方法

    类创建对象之初进行的函数,常与单例模式一起使用

    # new一个对象
    class A:
        def __init__(self):
            print(111)
        def __new__(cls):
            print(222)
            return object.__new__(cls)  #创造对象,将对象返回给__init__   如果不返回,讲不会执行__init__
    a = A()
    #输出:222
    #      111
    # 先执行__new__方法 创造出一个对象,
    # 然后把创造出来的对象传递给__init__方法(先执行new,再执行init)
    # 会把self自动的返回,被a接收
    补充:元类——创建类的类
    
    type()  所有直接用class创建出来的类的元类都是type
    class 类名(B,classMeta = 元类名)
    class 类名(B,classMeta = type)  默认  
    元类 创造 类     所以所有的类的type都是它的元类,默认是type
    类   创造 对象   具体创造对象的方法 __new__方法,所有的对象的type都是它对应的类
    设计模式——单例模式—:  一个类 可以被多次实例化 但是同一时间在python的内存中,只能有一个实例

     单例模式:

    一个普通的类,在实例化的时候,可以同时实例化多个对象(多个对象一起执行,都存在内存地址里),单例模式就是只能存在一个

    class A:
        _instance = None                  #设置一个空
        def __init__(self,name):
            '''给娃穿衣服'''
            self.name = name
        def __new__(cls, *args, **kwargs):
            '''生娃的过程'''
            if not A._instance:        #当_instance为空时,进入此条件
                A._instance = object.__new__(cls)  #创造对象,赋给_instance,返回
            return A._instance         #当_instance不为空时,说明已经实例化一次,则直接返回之前那得对象
    a1 = A('liu')  # 第一次实例化的时候创造一个实例
    print(a1.name)    #打印liu
    a2 = A('lin')   
    print(a1.name,a2.name)   #打印 lin  lin    因为只允许实例化一次,两次实例化是内存地址一样,所以两个值一样
    class A:
        def __init__(self,name):
            '''给娃穿衣服'''
            self.name = name
        def __new__(cls, *args, **kwargs):
            '''生娃的过程'''
            if not hasattr(A,'_instance'):#判断如果没有此对象
                A._instance = object.__new__(cls)
            return A._instance
    a1 = A('alex')  # 第一次实例化的时候创造一个实例
    print(a1.name) #alex
    a2 = A('egon')
    print(a1.name,a2.name)  #egon egon
    单例另一种写法(hasattr)

    3、item系列

    __getitem__  找   __setitem__  新建   __delitem__  删除   __delattr__  删除

    通过上述方法  实现类似字典一样的操作

    class Foo:
        def __init__(self,name):
            self.name=name
    
        def __getitem__(self, item):
            print(self.__dict__[item])
    
        def __setitem__(self, key, value):
            self.__dict__[key]=value
        def __delitem__(self, key):
            print('del obj[key]时,我执行')
            self.__dict__.pop(key)
        def __delattr__(self, key):
            print('del obj.key时,我执行')
            del self.__dict__[key]
    
    f1=Foo('sb')
    f1['age']=18
    f1['age1']=19del f1['age']
    f1['name']='liulin'
    print(f1.__dict__)

    __call__

    对象名加括号,调用类中内置__call__ 方法

    class A:
        def __call__(self):
            print('执行我了')
    A()() #实例化 ()
    #执行我了

    __hash__

    # hash
    # 不可变的数据类型都可以被hash
    # dict的key   set的元素
    # dic key --> value
    # dic[key] = value
     
    class A:
        def __init__(self):
            self.a = 1
            self.b = 2
    
        def __hash__(self):
            return hash(str(self.a)+str(self.b))
    a = A()
    print(hash(a))
    View Code
    
    

    依据hash和set(集合)完成的金融面试题

    # 金融公司面试题
    # 有一个类,对应这个类产生了100个对象
    # 每个对象有三个属性 : 姓名 年龄 性别
    # 请对这一百个对象进行去重,如果姓名和性别相同,即便年龄不同也是相同的对象
    # 问最简便的方法?
    class Person:
        def __init__(self,name,age,sex):
            self.name = name
            self.age = age
            self.sex = sex
        def __hash__(self):
            return hash('%s%s'%(self.name,self.sex))
        def __eq__(self, other):
            if self.name == other.name and  
                self.sex == other.sex:
                return True
    p_lst = []
    for i in range(100):
        p_lst.append(Person('egon',i,'male'))
    p_lst.append(Person('alex',i,'male'))
    p_lst.append(Person('yuan',i,'male'))
    print(p_lst)
    print(set(p_lst))
    收获1
    对于一些python当中已经存在的内置函数 内置数据类型 内置模块中的方法
    都有可能依赖于类中的内置方法
    收获2
    set方法依赖集合中元素对象的__hash__ __eq__


  • 相关阅读:
    SQL 去重 DISTINCT 语法
    urllib2 urllib urllib3的区别联系
    urllib库中常见的类和方法
    python模块之json pickle
    python os模块
    python的常见内置模块之-----time
    列表,队列,栈,链表的内存模型
    open函数
    session和cookie
    随笔小skill
  • 原文地址:https://www.cnblogs.com/pygg/p/8559402.html
Copyright © 2011-2022 走看看