类的内置方法 __del__ 析构方法 __new__(面试) __call__ __len__ __hash__ __eq__

自定制格式化字符串__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
# 班级 : 北京
# =====================

析构方法

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

注:此方法一般无须定义,因为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))