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

    自定制格式化字符串__format__

    __str__  ,   __repr__(优先使用,覆盖面广)

    改变对象的字符串显示__str__,__repr__

    class A:pass
    a = A()
    print(a) # <__main__.A object at 0x0000000001DD1D68>内存地址 自己找不到到父类找
    l = list()
    print(l)  # []  为什么打出来长上面的不一样,因为list里面有内置方法

    print(a.__str__()) # <__main__.A object at 0x00000000021C7A20> # 打印一个对象的时候,实际上市调用了这个对象所在类的__str__方法,打印的是这个方法的返回值 print('%s'%a) # <__main__.A object at 0x0000000002197A58> # %s 就是__str__方法的返回值 # 类的双下划线方法 # __str__ 和 __repr__

    自己定制str方法
    class A: def __str__(self): return 'a的对象' # str必须return一个字符串 def __repr__(self): return 'repr:A的对象' a = A() print(a.__str__()) # a的对象 print(a.__repr__()) # repr:A的对象 repr是str的备胎,没有str就用repr # repr是str的备胎,没有str就用repr (repr比较随和) # str 却不能给repr做备胎 (str高冷 ) class A: # def __str__(self): # return 'a的对象' # str必须return一个字符串 def __repr__(self): return 'repr:A的对象' a = A() print(a) # repr:A的对象 # 本质调用 __str__, 如果没有实现,就调用__repr__,再找不到,用object父类的 print(a.__str__()) # repr:A的对象 print(a.__repr__()) # repr:A的对象 print('%s'%a) # repr:A的对象 # 打印一个对象的时候,实际上是调用了这个对象所在类的__str__方法,打印的是这个方法的返回值

    %s  %r

    class A:
        def __str__(self):
            return 'a的对象'  # str必须return一个字符串
    
        def __repr__(self):
            return 'repr:A的对象'
    
    a = A()
    print(a.__str__())  # a的对象
    print(a.__repr__())  # repr:A的对象  repr是str的备胎,没有str就用repr
    print('%s'%a)  # s -- 》 str  a的对象(自己有用自己)
    print('%r'%a)  # r --》 repr  repr:A的对象

    自定制格式化字符串__format__

    格式

    # format_dict={
    #     'nat':'{o.name}-{o.addr}-{o.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): #format_spec = 'nat'  相当与上面
            fmt='{obj.type}:{obj.name}:{obj.addr}'  # 做格式化输出
            return fmt.format(obj=self)  # 这里obj=self为固定写法
    
    s1=School('oldboy1','北京','私立')
    print(format(s1,'nat'))
    print(format(s1,'tna'))
    print(format(s1,'tan'))
    print(format(s1,'asfdasdffd'))

    例子

    class School:
        def __init__(self,name,addr,type):
            self.name=name
            self.addr=addr
            self.type=type
    
        def __format__(self, format_spec): #format_spec = 'nat'
            fmt='''=====================
    姓名 : {obj.name}
    班级 : {obj.addr}
    ====================='''
            return fmt.format(obj=self)
    
    s1=School('oldboy1','北京','私立')
    print(format(s1,'nat'))
    print(format(s1,'tna'))
    print(format(s1,'tan'))
    print(format(s1,'asfdasdffd'))
    
    # 输出的格式
    # =====================
    # 姓名 : oldboy1
    # 班级 : 北京
    # =====================
    # =====================
    # 姓名 : oldboy1
    # 班级 : 北京
    # =====================
    # =====================
    # 姓名 : oldboy1
    # 班级 : 北京
    # =====================
    # =====================
    # 姓名 : oldboy1
    # 班级 : 北京
    # =====================

    __del__

    析构方法

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

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

      析构方法(是执行删除对象的时候才执行)700百才启动
    具有周期: 当没引用

    须知道: 当你删除一个对象的时候,这个对象的相关内容,需做一些处理,就使用析构方法

    # 用于高并发问题
    class A:
        def __del__(self):
            '''
            析构方法
            这个方法只有在执行del A类的对象的时候才被触发
            且先执行代码中的内容,再删除对象
            如果我删除了这个对象,它跟着还有一些其他的附属的内容也没有用了
            我们就可以在这个方法中回收掉
            '''
            print('执行我啦!')
            self.b.close()
    f = open('file','w')
    a = A()  # 对象
    a.b = f  # 给a的对象赋一个文件句柄
    del a  # 即文件不需要了

     

    item系列方法

    __getitem__\__setitem__\__delitem__

    需求:

    使用[] 去获取对象里面内容的方法,实现,调用就使用item系列方法

    #关于item : 对象访问 如果是 对象名[],是因为内部实现了item系列的方法

    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, item):
            print('del obj.key时,我执行')
            self.__dict__.pop(item)
    
    f1 = Foo('sb')
    # 访问属性的方式变了
    # 对象名.属性
    f1=Foo('sb')
    f1['age']=18  #给f1添加一个属性
          #  触发 __setitem__(self, key, value)  ---》 key = age ,value = 18
    
    del f1['age']  #删除属性  __delitem__(self, key)
    
    print(f1['name'])  # f1.name 正常以前访问
           # 触发了__getitem__(self, item) --> item = name
    
    f1.__dict__['age'] = 18
    f1['age1']=19
    del f1.age1   #删除属性
    
    f1['name']='alex'
    print(f1.__dict__)
    class Foo:
        def __init__(self,name):
            self.name=name
        def __getitem__(self, item):
            if item == 1:
                print('hahaha')
        def __setitem__(self, key, value):
            self.__dict__[key]=value
        def __delitem__(self, key):
            print('del obj[key]时,我执行')
            self.__dict__.pop(key)
        def __delattr__(self, item):
            print('del obj.key时,我执行')
            self.__dict__.pop(item)
    
    f1 = Foo('sb')
    f1[1]
    
    # 输出 hahha

    __new__(面试)

    是object替你执行new方法

    对象的实例化
    创造一个裸地对象 —— __new__ ****
    初始化
    单例模式 —— 设计模式(面试)
    一个类 从头到尾 只创建 一个对象
    
    
    class Singleton:
        def __new__(cls, *args):
            if not hasattr(cls, '_instance'):
                cls._instance = object.__new__(cls)  # 创造一个新对象
            return cls._instance
    
        def __init__(self,name):
            self.name = name
    
    one = Singleton('alex') # object.__new__(elax)
    print(one.name) # alex
    two = one
    two.name = 'egon'
    two = Singleton('egon')
    print(two.name)  # egon
    print(one.name)  # egon
    print(id(one),id(two))  # 38785880 38785880
    
    

    __call__

    ()跟call是约定的

    对象后面加括号,触发执行。

    
    

    注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()

     
    class Foo:
        def __init__(self):
            pass
    
        def __call__(self, *args, **kwargs):
            print('__call__')
    
    Foo()()   #对象名() ---> 调用call

    __len__

    class A:
        def __init__(self):
            self.a = 1
            self.b = 2
    
        def __len__(self):
            return len(self.__dict__)
    a = A()
    print(len(a))

    __hash__

    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))

    __eq__

    class A:
        def __init__(self):
            self.a = 1
            self.b = 2
    
        def __eq__(self,obj):
            if  self.a == obj.a and self.b == obj.b:
                return True
    a = A()
    b = A()
    print(a == b)

    例子

    class A:
        def __eq__(self,obj):   #equal : 相等
            # if  self.a == obj.a and self.b == obj.b:
                return True
    a = A()
    b = A()
    a.name = 'alex'
    b.name = 'egon'
    print(a == b)  # True

    面试题

    一个类 有 100个 对象,每一个对象都拥有三个属性:name,sex,age
    如果两个对象的name和sex属性完全一致
    我就认为这是一个对象
    请对这100个对象进行去重
    class Person:
        def __init__(self,name,age,sex):
            self.name = name
            self.age = age
            self.sex = sex
        def __hash__(self):
            return hash(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(84):
        p_lst.append(Person('egon',i,'male'))
    print(set(p_lst))
     
  • 相关阅读:
    Apache部署Django项目
    Docker
    常用算法
    Go之基本数据类型
    Go之流程控制
    Go基本使用
    Go安装与Goland破解永久版
    Linux
    详解java中的byte类型
    Linux统计文本中某个字符串出现的次数
  • 原文地址:https://www.cnblogs.com/jassin-du/p/7893839.html
Copyright © 2011-2022 走看看